Linux Audio

Check our new training course

Loading...
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/device.h>
  3#include <linux/kernel.h>
  4#include <linux/module.h>
  5#include <linux/io.h>
  6#include <linux/mcb.h>
  7#include <linux/serial.h>
  8#include <linux/serial_core.h>
  9#include <linux/serial_8250.h>
 10
 11#define MEN_UART_ID_Z025 0x19
 12#define MEN_UART_ID_Z057 0x39
 13#define MEN_UART_ID_Z125 0x7d
 14
 15/*
 16 * IP Cores Z025 and Z057 can have up to 4 UART
 17 * The UARTs available are stored in a global
 18 * register saved in physical address + 0x40
 19 * Is saved as follows:
 20 *
 21 * 7                                                              0
 22 * +------+-------+-------+-------+-------+-------+-------+-------+
 23 * |UART4 | UART3 | UART2 | UART1 | U4irq | U3irq | U2irq | U1irq |
 24 * +------+-------+-------+-------+-------+-------+-------+-------+
 25 */
 26#define MEN_UART1_MASK	0x01
 27#define MEN_UART2_MASK	0x02
 28#define MEN_UART3_MASK	0x04
 29#define MEN_UART4_MASK	0x08
 30
 31#define MEN_Z125_UARTS_AVAILABLE	0x01
 32
 33#define MEN_Z025_MAX_UARTS		4
 34#define MEN_UART_MEM_SIZE		0x10
 35#define MEM_UART_REGISTER_SIZE		0x01
 36#define MEN_Z025_REGISTER_OFFSET	0x40
 37
 38#define MEN_UART1_OFFSET	0
 39#define MEN_UART2_OFFSET	(MEN_UART1_OFFSET + MEN_UART_MEM_SIZE)
 40#define MEN_UART3_OFFSET	(MEN_UART2_OFFSET + MEN_UART_MEM_SIZE)
 41#define MEN_UART4_OFFSET	(MEN_UART3_OFFSET + MEN_UART_MEM_SIZE)
 42
 43#define MEN_READ_REGISTER(addr)	readb(addr)
 44
 45#define MAX_PORTS	4
 46
 47struct serial_8250_men_mcb_data {
 48	int num_ports;
 49	int line[MAX_PORTS];
 50	unsigned int offset[MAX_PORTS];
 51};
 52
 53/*
 54 * The Z125 16550-compatible UART has no fixed base clock assigned
 55 * So, depending on the board we're on, we need to adjust the
 56 * parameter in order to really set the correct baudrate, and
 57 * do so if possible without user interaction
 58 */
 59static u32 men_lookup_uartclk(struct mcb_device *mdev)
 60{
 61	/* use default value if board is not available below */
 62	u32 clkval = 1041666;
 63
 64	dev_info(&mdev->dev, "%s on board %s\n",
 65		dev_name(&mdev->dev),
 66		mdev->bus->name);
 67	if  (strncmp(mdev->bus->name, "F075", 4) == 0)
 68		clkval = 1041666;
 69	else if (strncmp(mdev->bus->name, "F216", 4) == 0)
 70		clkval = 1843200;
 
 
 71	else if (strncmp(mdev->bus->name, "F210", 4) == 0)
 72		clkval = 115200;
 73	else if (strstr(mdev->bus->name, "215"))
 74		clkval = 1843200;
 75	else
 76		dev_info(&mdev->dev,
 77			 "board not detected, using default uartclk\n");
 78
 79	clkval = clkval  << 4;
 80
 81	return clkval;
 82}
 83
 84static int read_uarts_available_from_register(struct resource *mem_res,
 85					      u8 *uarts_available)
 86{
 87	void __iomem *mem;
 88	int reg_value;
 89
 90	if (!request_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
 91				MEM_UART_REGISTER_SIZE,  KBUILD_MODNAME)) {
 92		return -EBUSY;
 93	}
 94
 95	mem = ioremap(mem_res->start + MEN_Z025_REGISTER_OFFSET,
 96		      MEM_UART_REGISTER_SIZE);
 97	if (!mem) {
 98		release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
 99				   MEM_UART_REGISTER_SIZE);
100		return -ENOMEM;
101	}
102
103	reg_value = MEN_READ_REGISTER(mem);
104
105	iounmap(mem);
106
107	release_mem_region(mem_res->start + MEN_Z025_REGISTER_OFFSET,
108			   MEM_UART_REGISTER_SIZE);
109
110	*uarts_available = reg_value >> 4;
111
112	return 0;
113}
114
115static int read_serial_data(struct mcb_device *mdev,
116			    struct resource *mem_res,
117			    struct serial_8250_men_mcb_data *serial_data)
118{
119	u8 uarts_available;
120	int count = 0;
121	int mask;
122	int res;
123	int i;
124
125	res = read_uarts_available_from_register(mem_res, &uarts_available);
126	if (res < 0)
127		return res;
128
129	for (i = 0; i < MAX_PORTS; i++) {
130		mask = 0x1 << i;
131		switch (uarts_available & mask) {
132		case MEN_UART1_MASK:
133			serial_data->offset[count] = MEN_UART1_OFFSET;
134			count++;
135			break;
136		case MEN_UART2_MASK:
137			serial_data->offset[count] = MEN_UART2_OFFSET;
138			count++;
139			break;
140		case MEN_UART3_MASK:
141			serial_data->offset[count] = MEN_UART3_OFFSET;
142			count++;
143			break;
144		case MEN_UART4_MASK:
145			serial_data->offset[count] = MEN_UART4_OFFSET;
146			count++;
147			break;
148		default:
149			return -EINVAL;
150		}
151	}
152
153	if (count <= 0 || count > MAX_PORTS) {
154		dev_err(&mdev->dev, "unexpected number of ports: %u\n",
155			count);
156		return -ENODEV;
157	}
158
159	serial_data->num_ports = count;
160
161	return 0;
162}
163
164static int init_serial_data(struct mcb_device *mdev,
165			    struct resource *mem_res,
166			    struct serial_8250_men_mcb_data *serial_data)
167{
168	switch (mdev->id) {
169	case MEN_UART_ID_Z125:
170		serial_data->num_ports = 1;
171		serial_data->offset[0] = 0;
172		return 0;
173	case MEN_UART_ID_Z025:
 
174	case MEN_UART_ID_Z057:
175		return read_serial_data(mdev, mem_res, serial_data);
176	default:
177		dev_err(&mdev->dev, "no supported device!\n");
178		return -ENODEV;
179	}
180}
181
182static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
183				     const struct mcb_device_id *id)
184{
185	struct uart_8250_port uart;
186	struct serial_8250_men_mcb_data *data;
187	struct resource *mem;
 
188	int i;
189	int res;
190
191	mem = mcb_get_resource(mdev, IORESOURCE_MEM);
192	if (mem == NULL)
193		return -ENXIO;
 
 
 
 
 
 
 
 
194
195	data = devm_kzalloc(&mdev->dev,
 
 
 
 
 
 
196			    sizeof(struct serial_8250_men_mcb_data),
197			    GFP_KERNEL);
198	if (!data)
199		return -ENOMEM;
200
201	res = init_serial_data(mdev, mem, data);
202	if (res < 0)
203		return res;
204
205	dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
206		mdev->id, data->num_ports);
207
208	mcb_set_drvdata(mdev, data);
209
210	for (i = 0; i < data->num_ports; i++) {
211		memset(&uart, 0, sizeof(struct uart_8250_port));
212		spin_lock_init(&uart.port.lock);
213
214		uart.port.flags = UPF_SKIP_TEST |
215				  UPF_SHARE_IRQ |
216				  UPF_BOOT_AUTOCONF |
217				  UPF_IOREMAP;
218		uart.port.iotype = UPIO_MEM;
219		uart.port.uartclk = men_lookup_uartclk(mdev);
220		uart.port.irq = mcb_get_irq(mdev);
221		uart.port.mapbase = (unsigned long) mem->start
222					    + data->offset[i];
 
 
 
223
224		/* ok, register the port */
225		res = serial8250_register_8250_port(&uart);
226		if (res < 0) {
227			dev_err(&mdev->dev, "unable to register UART port\n");
228			return res;
229		}
230
231		data->line[i] = res;
232		dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data->line[i]);
233	}
234
235	return 0;
236}
237
238static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
239{
240	int i;
241	struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
242
243	if (!data)
244		return;
245
246	for (i = 0; i < data->num_ports; i++)
247		serial8250_unregister_port(data->line[i]);
 
 
 
 
 
 
248}
249
250static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
251	{ .device = MEN_UART_ID_Z025 },
252	{ .device = MEN_UART_ID_Z057 },
253	{ .device = MEN_UART_ID_Z125 },
254	{ }
255};
256MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
257
258static struct mcb_driver mcb_driver = {
259	.driver = {
260		.name = "8250_men_mcb",
 
261	},
262	.probe = serial_8250_men_mcb_probe,
263	.remove = serial_8250_men_mcb_remove,
264	.id_table = serial_8250_men_mcb_ids,
265};
266module_mcb_driver(mcb_driver);
267
268MODULE_LICENSE("GPL v2");
269MODULE_DESCRIPTION("MEN 8250 UART driver");
270MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
271MODULE_ALIAS("mcb:16z125");
272MODULE_ALIAS("mcb:16z025");
273MODULE_ALIAS("mcb:16z057");
274MODULE_IMPORT_NS(MCB);
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/device.h>
  3#include <linux/kernel.h>
  4#include <linux/module.h>
  5#include <linux/io.h>
  6#include <linux/mcb.h>
  7#include <linux/serial.h>
  8#include <linux/serial_core.h>
  9#include <linux/serial_8250.h>
 10
 11#define MEN_UART_ID_Z025 0x19
 12#define MEN_UART_ID_Z057 0x39
 13#define MEN_UART_ID_Z125 0x7d
 14
 15#define MEN_UART_MEM_SIZE 0x10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 16
 17struct serial_8250_men_mcb_data {
 18	struct uart_8250_port uart;
 19	int line;
 
 20};
 21
 22/*
 23 * The Z125 16550-compatible UART has no fixed base clock assigned
 24 * So, depending on the board we're on, we need to adjust the
 25 * parameter in order to really set the correct baudrate, and
 26 * do so if possible without user interaction
 27 */
 28static u32 men_lookup_uartclk(struct mcb_device *mdev)
 29{
 30	/* use default value if board is not available below */
 31	u32 clkval = 1041666;
 32
 33	dev_info(&mdev->dev, "%s on board %s\n",
 34		dev_name(&mdev->dev),
 35		mdev->bus->name);
 36	if  (strncmp(mdev->bus->name, "F075", 4) == 0)
 37		clkval = 1041666;
 38	else if (strncmp(mdev->bus->name, "F216", 4) == 0)
 39		clkval = 1843200;
 40	else if (strncmp(mdev->bus->name, "G215", 4) == 0)
 41		clkval = 1843200;
 42	else if (strncmp(mdev->bus->name, "F210", 4) == 0)
 43		clkval = 115200;
 
 
 44	else
 45		dev_info(&mdev->dev,
 46			 "board not detected, using default uartclk\n");
 47
 48	clkval = clkval  << 4;
 49
 50	return clkval;
 51}
 52
 53static int get_num_ports(struct mcb_device *mdev,
 54				  void __iomem *membase)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 55{
 56	switch (mdev->id) {
 57	case MEN_UART_ID_Z125:
 58		return 1U;
 
 
 59	case MEN_UART_ID_Z025:
 60		return readb(membase) >> 4;
 61	case MEN_UART_ID_Z057:
 62		return 4U;
 63	default:
 64		dev_err(&mdev->dev, "no supported device!\n");
 65		return -ENODEV;
 66	}
 67}
 68
 69static int serial_8250_men_mcb_probe(struct mcb_device *mdev,
 70				     const struct mcb_device_id *id)
 71{
 
 72	struct serial_8250_men_mcb_data *data;
 73	struct resource *mem;
 74	int num_ports;
 75	int i;
 76	void __iomem *membase;
 77
 78	mem = mcb_get_resource(mdev, IORESOURCE_MEM);
 79	if (mem == NULL)
 80		return -ENXIO;
 81	membase = devm_ioremap_resource(&mdev->dev, mem);
 82	if (IS_ERR(membase))
 83		return PTR_ERR_OR_ZERO(membase);
 84
 85	num_ports = get_num_ports(mdev, membase);
 86
 87	dev_dbg(&mdev->dev, "found a 16z%03u with %u ports\n",
 88		mdev->id, num_ports);
 89
 90	if (num_ports <= 0 || num_ports > 4) {
 91		dev_err(&mdev->dev, "unexpected number of ports: %u\n",
 92			num_ports);
 93		return -ENODEV;
 94	}
 95
 96	data = devm_kcalloc(&mdev->dev, num_ports,
 97			    sizeof(struct serial_8250_men_mcb_data),
 98			    GFP_KERNEL);
 99	if (!data)
100		return -ENOMEM;
101
 
 
 
 
 
 
 
102	mcb_set_drvdata(mdev, data);
103
104	for (i = 0; i < num_ports; i++) {
105		data[i].uart.port.dev = mdev->dma_dev;
106		spin_lock_init(&data[i].uart.port.lock);
107
108		data[i].uart.port.type = PORT_16550;
109		data[i].uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ
110					  | UPF_FIXED_TYPE;
111		data[i].uart.port.iotype = UPIO_MEM;
112		data[i].uart.port.uartclk = men_lookup_uartclk(mdev);
113		data[i].uart.port.regshift = 0;
114		data[i].uart.port.irq = mcb_get_irq(mdev);
115		data[i].uart.port.membase = membase;
116		data[i].uart.port.fifosize = 60;
117		data[i].uart.port.mapbase = (unsigned long) mem->start
118					    + i * MEN_UART_MEM_SIZE;
119		data[i].uart.port.iobase = data[i].uart.port.mapbase;
120
121		/* ok, register the port */
122		data[i].line = serial8250_register_8250_port(&data[i].uart);
123		if (data[i].line < 0) {
124			dev_err(&mdev->dev, "unable to register UART port\n");
125			return data[i].line;
126		}
127		dev_info(&mdev->dev, "found MCB UART: ttyS%d\n", data[i].line);
 
 
128	}
129
130	return 0;
131}
132
133static void serial_8250_men_mcb_remove(struct mcb_device *mdev)
134{
135	int num_ports, i;
136	struct serial_8250_men_mcb_data *data = mcb_get_drvdata(mdev);
137
138	if (!data)
139		return;
140
141	num_ports = get_num_ports(mdev, data[0].uart.port.membase);
142	if (num_ports <= 0 || num_ports > 4) {
143		dev_err(&mdev->dev, "error retrieving number of ports!\n");
144		return;
145	}
146
147	for (i = 0; i < num_ports; i++)
148		serial8250_unregister_port(data[i].line);
149}
150
151static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
152	{ .device = MEN_UART_ID_Z025 },
153	{ .device = MEN_UART_ID_Z057 },
154	{ .device = MEN_UART_ID_Z125 },
155	{ }
156};
157MODULE_DEVICE_TABLE(mcb, serial_8250_men_mcb_ids);
158
159static struct mcb_driver mcb_driver = {
160	.driver = {
161		.name = "8250_men_mcb",
162		.owner = THIS_MODULE,
163	},
164	.probe = serial_8250_men_mcb_probe,
165	.remove = serial_8250_men_mcb_remove,
166	.id_table = serial_8250_men_mcb_ids,
167};
168module_mcb_driver(mcb_driver);
169
170MODULE_LICENSE("GPL v2");
171MODULE_DESCRIPTION("MEN 8250 UART driver");
172MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
173MODULE_ALIAS("mcb:16z125");
174MODULE_ALIAS("mcb:16z025");
175MODULE_ALIAS("mcb:16z057");
176MODULE_IMPORT_NS(MCB);