2 * Probe for F81216A LPC to 4 UART
4 * Copyright (C) 2014-2016 Ricardo Ribalda, Qtechnology A/S
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License.
11 #include <linux/module.h>
12 #include <linux/pci.h>
13 #include <linux/pnp.h>
14 #include <linux/kernel.h>
15 #include <linux/serial_core.h>
16 #include <linux/irq.h>
24 #define CHIP_ID_0 0x1602
25 #define CHIP_ID_1 0x0501
26 #define VENDOR_ID1 0x23
27 #define VENDOR_ID1_VAL 0x19
28 #define VENDOR_ID2 0x24
29 #define VENDOR_ID2_VAL 0x34
35 #define IRQ_SHARE BIT(4)
36 #define IRQ_MODE_MASK (BIT(6) | BIT(5))
37 #define IRQ_LEVEL_LOW 0
38 #define IRQ_EDGE_HIGH BIT(5)
41 #define RTS_INVERT BIT(5)
42 #define RS485_URA BIT(4)
43 #define RXW4C_IRA BIT(3)
44 #define TXW4C_IRA BIT(2)
52 static int fintek_8250_enter_key(u16 base_port
, u8 key
)
54 if (!request_muxed_region(base_port
, 2, "8250_fintek"))
57 outb(key
, base_port
+ ADDR_PORT
);
58 outb(key
, base_port
+ ADDR_PORT
);
62 static void fintek_8250_exit_key(u16 base_port
)
65 outb(EXIT_KEY
, base_port
+ ADDR_PORT
);
66 release_region(base_port
+ ADDR_PORT
, 2);
69 static int fintek_8250_check_id(u16 base_port
)
73 outb(VENDOR_ID1
, base_port
+ ADDR_PORT
);
74 if (inb(base_port
+ DATA_PORT
) != VENDOR_ID1_VAL
)
77 outb(VENDOR_ID2
, base_port
+ ADDR_PORT
);
78 if (inb(base_port
+ DATA_PORT
) != VENDOR_ID2_VAL
)
81 outb(CHIP_ID1
, base_port
+ ADDR_PORT
);
82 chip
= inb(base_port
+ DATA_PORT
);
83 outb(CHIP_ID2
, base_port
+ ADDR_PORT
);
84 chip
|= inb(base_port
+ DATA_PORT
) << 8;
86 if (chip
!= CHIP_ID_0
&& chip
!= CHIP_ID_1
)
92 static int fintek_8250_rs485_config(struct uart_port
*port
,
93 struct serial_rs485
*rs485
)
96 struct fintek_8250
*pdata
= port
->private_data
;
101 if (rs485
->flags
& SER_RS485_ENABLED
)
102 memset(rs485
->padding
, 0, sizeof(rs485
->padding
));
104 memset(rs485
, 0, sizeof(*rs485
));
106 rs485
->flags
&= SER_RS485_ENABLED
| SER_RS485_RTS_ON_SEND
|
107 SER_RS485_RTS_AFTER_SEND
;
109 if (rs485
->delay_rts_before_send
) {
110 rs485
->delay_rts_before_send
= 1;
114 if (rs485
->delay_rts_after_send
) {
115 rs485
->delay_rts_after_send
= 1;
119 if ((!!(rs485
->flags
& SER_RS485_RTS_ON_SEND
)) ==
120 (!!(rs485
->flags
& SER_RS485_RTS_AFTER_SEND
)))
121 rs485
->flags
&= SER_RS485_ENABLED
;
125 if (rs485
->flags
& SER_RS485_RTS_ON_SEND
)
126 config
|= RTS_INVERT
;
128 if (fintek_8250_enter_key(pdata
->base_port
, pdata
->key
))
131 outb(LDN
, pdata
->base_port
+ ADDR_PORT
);
132 outb(pdata
->index
, pdata
->base_port
+ DATA_PORT
);
133 outb(RS485
, pdata
->base_port
+ ADDR_PORT
);
134 outb(config
, pdata
->base_port
+ DATA_PORT
);
135 fintek_8250_exit_key(pdata
->base_port
);
137 port
->rs485
= *rs485
;
142 static int find_base_port(struct fintek_8250
*pdata
, u16 io_address
)
144 static const u16 addr
[] = {0x4e, 0x2e};
145 static const u8 keys
[] = {0x77, 0xa0, 0x87, 0x67};
148 for (i
= 0; i
< ARRAY_SIZE(addr
); i
++) {
149 for (j
= 0; j
< ARRAY_SIZE(keys
); j
++) {
151 if (fintek_8250_enter_key(addr
[i
], keys
[j
]))
153 if (fintek_8250_check_id(addr
[i
])) {
154 fintek_8250_exit_key(addr
[i
]);
158 for (k
= 0; k
< 4; k
++) {
161 outb(LDN
, addr
[i
] + ADDR_PORT
);
162 outb(k
, addr
[i
] + DATA_PORT
);
164 outb(IO_ADDR1
, addr
[i
] + ADDR_PORT
);
165 aux
= inb(addr
[i
] + DATA_PORT
);
166 outb(IO_ADDR2
, addr
[i
] + ADDR_PORT
);
167 aux
|= inb(addr
[i
] + DATA_PORT
) << 8;
168 if (aux
!= io_address
)
171 fintek_8250_exit_key(addr
[i
]);
172 pdata
->key
= keys
[j
];
173 pdata
->base_port
= addr
[i
];
179 fintek_8250_exit_key(addr
[i
]);
186 static int fintek_8250_set_irq_mode(struct fintek_8250
*pdata
, bool level_mode
)
191 status
= fintek_8250_enter_key(pdata
->base_port
, pdata
->key
);
195 outb(LDN
, pdata
->base_port
+ ADDR_PORT
);
196 outb(pdata
->index
, pdata
->base_port
+ DATA_PORT
);
198 outb(IRQ_MODE
, pdata
->base_port
+ ADDR_PORT
);
199 tmp
= inb(pdata
->base_port
+ DATA_PORT
);
201 tmp
&= ~IRQ_MODE_MASK
;
204 tmp
|= IRQ_EDGE_HIGH
;
206 outb(tmp
, pdata
->base_port
+ DATA_PORT
);
207 fintek_8250_exit_key(pdata
->base_port
);
211 int fintek_8250_probe(struct uart_8250_port
*uart
)
213 struct fintek_8250
*pdata
;
214 struct fintek_8250 probe_data
;
215 struct irq_data
*irq_data
= irq_get_irq_data(uart
->port
.irq
);
216 bool level_mode
= irqd_is_level_type(irq_data
);
218 if (find_base_port(&probe_data
, uart
->port
.iobase
))
221 pdata
= devm_kzalloc(uart
->port
.dev
, sizeof(*pdata
), GFP_KERNEL
);
225 memcpy(pdata
, &probe_data
, sizeof(probe_data
));
226 uart
->port
.rs485_config
= fintek_8250_rs485_config
;
227 uart
->port
.private_data
= pdata
;
229 return fintek_8250_set_irq_mode(pdata
, level_mode
);
This page took 0.034378 seconds and 5 git commands to generate.