aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/cpm_uart
diff options
context:
space:
mode:
authorVitaly Bordug <vbordug@ru.mvista.com>2006-04-25 12:26:41 -0400
committerPaul Mackerras <paulus@samba.org>2006-04-28 07:11:28 -0400
commite27987cddd8db3a72a0f4734b5d94d06c7677323 (patch)
treeacc8df71f7cccd5ac24cb894cbf6ffabab4b0feb /drivers/serial/cpm_uart
parenta73c87bfe98f4d54c919e920a6efb0a116115722 (diff)
[PATCH] ppc32 CPM_UART: Convert to use platform devices
This is intended to make the driver code more generic and flexible, to get rid of board-specific layouts within driver, and generic rehaul, yet keeping compatibility with the existing stuff utilizing it, being compatible with legacy behavior (but with complaints that legacy mode used). Signed-off-by: Vitaly Bordug <vbordug@ru.mvista.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers/serial/cpm_uart')
-rw-r--r--drivers/serial/cpm_uart/cpm_uart.h16
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_core.c259
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm1.c47
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c9
4 files changed, 220 insertions, 111 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 73c8a088c16..17f2c7aa450 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -10,6 +10,8 @@
10#define CPM_UART_H 10#define CPM_UART_H
11 11
12#include <linux/config.h> 12#include <linux/config.h>
13#include <linux/platform_device.h>
14#include <linux/fs_uart_pd.h>
13 15
14#if defined(CONFIG_CPM2) 16#if defined(CONFIG_CPM2)
15#include "cpm_uart_cpm2.h" 17#include "cpm_uart_cpm2.h"
@@ -26,14 +28,14 @@
26#define FLAG_SMC 0x00000002 28#define FLAG_SMC 0x00000002
27#define FLAG_CONSOLE 0x00000001 29#define FLAG_CONSOLE 0x00000001
28 30
29#define UART_SMC1 0 31#define UART_SMC1 fsid_smc1_uart
30#define UART_SMC2 1 32#define UART_SMC2 fsid_smc2_uart
31#define UART_SCC1 2 33#define UART_SCC1 fsid_scc1_uart
32#define UART_SCC2 3 34#define UART_SCC2 fsid_scc2_uart
33#define UART_SCC3 4 35#define UART_SCC3 fsid_scc3_uart
34#define UART_SCC4 5 36#define UART_SCC4 fsid_scc4_uart
35 37
36#define UART_NR 6 38#define UART_NR fs_uart_nr
37 39
38#define RX_NUM_FIFO 4 40#define RX_NUM_FIFO 4
39#define RX_BUF_SIZE 32 41#define RX_BUF_SIZE 32
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b7bf4c698a4..9a5b044ce06 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -41,6 +41,7 @@
41#include <linux/device.h> 41#include <linux/device.h>
42#include <linux/bootmem.h> 42#include <linux/bootmem.h>
43#include <linux/dma-mapping.h> 43#include <linux/dma-mapping.h>
44#include <linux/fs_uart_pd.h>
44 45
45#include <asm/io.h> 46#include <asm/io.h>
46#include <asm/irq.h> 47#include <asm/irq.h>
@@ -60,7 +61,7 @@
60/* Track which ports are configured as uarts */ 61/* Track which ports are configured as uarts */
61int cpm_uart_port_map[UART_NR]; 62int cpm_uart_port_map[UART_NR];
62/* How many ports did we config as uarts */ 63/* How many ports did we config as uarts */
63int cpm_uart_nr; 64int cpm_uart_nr = 0;
64 65
65/**************************************************************/ 66/**************************************************************/
66 67
@@ -85,6 +86,37 @@ static inline void *cpm2cpu_addr(unsigned long addr)
85 return bus_to_virt(addr); 86 return bus_to_virt(addr);
86} 87}
87 88
89/* Place-holder for board-specific stuff */
90struct platform_device* __attribute__ ((weak)) __init
91early_uart_get_pdev(int index)
92{
93 return NULL;
94}
95
96
97void cpm_uart_count(void)
98{
99 cpm_uart_nr = 0;
100#ifdef CONFIG_SERIAL_CPM_SMC1
101 cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
102#endif
103#ifdef CONFIG_SERIAL_CPM_SMC2
104 cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
105#endif
106#ifdef CONFIG_SERIAL_CPM_SCC1
107 cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
108#endif
109#ifdef CONFIG_SERIAL_CPM_SCC2
110 cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
111#endif
112#ifdef CONFIG_SERIAL_CPM_SCC3
113 cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
114#endif
115#ifdef CONFIG_SERIAL_CPM_SCC4
116 cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
117#endif
118}
119
88/* 120/*
89 * Check, if transmit buffers are processed 121 * Check, if transmit buffers are processed
90*/ 122*/
@@ -829,14 +861,6 @@ static int cpm_uart_request_port(struct uart_port *port)
829 if (pinfo->flags & FLAG_CONSOLE) 861 if (pinfo->flags & FLAG_CONSOLE)
830 return 0; 862 return 0;
831 863
832 /*
833 * Setup any port IO, connect any baud rate generators,
834 * etc. This is expected to be handled by board
835 * dependant code
836 */
837 if (pinfo->set_lineif)
838 pinfo->set_lineif(pinfo);
839
840 if (IS_SMC(pinfo)) { 864 if (IS_SMC(pinfo)) {
841 pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); 865 pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
842 pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); 866 pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -988,6 +1012,54 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
988 }, 1012 },
989}; 1013};
990 1014
1015int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
1016{
1017 struct resource *r;
1018 struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
1019 int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */
1020 struct uart_cpm_port *pinfo;
1021 int line;
1022 u32 mem, pram;
1023
1024 for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);
1025
1026 pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
1027
1028 pinfo->brg = pdata->brg;
1029
1030 if (!is_con) {
1031 pinfo->port.line = line;
1032 pinfo->port.flags = UPF_BOOT_AUTOCONF;
1033 }
1034
1035 if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
1036 return -EINVAL;
1037 mem = r->start;
1038
1039 if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
1040 return -EINVAL;
1041 pram = r->start;
1042
1043 if(idx > fsid_smc2_uart) {
1044 pinfo->sccp = (scc_t *)mem;
1045 pinfo->sccup = (scc_uart_t *)pram;
1046 } else {
1047 pinfo->smcp = (smc_t *)mem;
1048 pinfo->smcup = (smc_uart_t *)pram;
1049 }
1050 pinfo->tx_nrfifos = pdata->tx_num_fifo;
1051 pinfo->tx_fifosize = pdata->tx_buf_size;
1052
1053 pinfo->rx_nrfifos = pdata->rx_num_fifo;
1054 pinfo->rx_fifosize = pdata->rx_buf_size;
1055
1056 pinfo->port.uartclk = pdata->uart_clk;
1057 pinfo->port.mapbase = (unsigned long)mem;
1058 pinfo->port.irq = platform_get_irq(pdev, 0);
1059
1060 return 0;
1061}
1062
991#ifdef CONFIG_SERIAL_CPM_CONSOLE 1063#ifdef CONFIG_SERIAL_CPM_CONSOLE
992/* 1064/*
993 * Print a string to the serial port trying not to disturb 1065 * Print a string to the serial port trying not to disturb
@@ -1067,9 +1139,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
1067 pinfo->tx_cur = (volatile cbd_t *) bdp; 1139 pinfo->tx_cur = (volatile cbd_t *) bdp;
1068} 1140}
1069 1141
1070/* 1142
1071 * Setup console. Be careful is called early !
1072 */
1073static int __init cpm_uart_console_setup(struct console *co, char *options) 1143static int __init cpm_uart_console_setup(struct console *co, char *options)
1074{ 1144{
1075 struct uart_port *port; 1145 struct uart_port *port;
@@ -1080,9 +1150,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
1080 int flow = 'n'; 1150 int flow = 'n';
1081 int ret; 1151 int ret;
1082 1152
1153 struct fs_uart_platform_info *pdata;
1154 struct platform_device* pdev = early_uart_get_pdev(co->index);
1155
1083 port = 1156 port =
1084 (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]]; 1157 (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
1085 pinfo = (struct uart_cpm_port *)port; 1158 pinfo = (struct uart_cpm_port *)port;
1159 if (!pdev) {
1160 pr_info("cpm_uart: console: compat mode\n");
1161 /* compatibility - will be cleaned up */
1162 cpm_uart_init_portdesc();
1163
1164 if (pinfo->set_lineif)
1165 pinfo->set_lineif(pinfo);
1166 } else {
1167 pdata = pdev->dev.platform_data;
1168 if (pdata)
1169 if (pdata->init_ioports)
1170 pdata->init_ioports();
1171
1172 cpm_uart_drv_get_platform_data(pdev, 1);
1173 }
1086 1174
1087 pinfo->flags |= FLAG_CONSOLE; 1175 pinfo->flags |= FLAG_CONSOLE;
1088 1176
@@ -1097,14 +1185,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
1097 baud = 9600; 1185 baud = 9600;
1098 } 1186 }
1099 1187
1100 /*
1101 * Setup any port IO, connect any baud rate generators,
1102 * etc. This is expected to be handled by board
1103 * dependant code
1104 */
1105 if (pinfo->set_lineif)
1106 pinfo->set_lineif(pinfo);
1107
1108 if (IS_SMC(pinfo)) { 1188 if (IS_SMC(pinfo)) {
1109 pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX); 1189 pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
1110 pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN); 1190 pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -1143,11 +1223,8 @@ static struct console cpm_scc_uart_console = {
1143 1223
1144int __init cpm_uart_console_init(void) 1224int __init cpm_uart_console_init(void)
1145{ 1225{
1146 int ret = cpm_uart_init_portdesc(); 1226 register_console(&cpm_scc_uart_console);
1147 1227 return 0;
1148 if (!ret)
1149 register_console(&cpm_scc_uart_console);
1150 return ret;
1151} 1228}
1152 1229
1153console_initcall(cpm_uart_console_init); 1230console_initcall(cpm_uart_console_init);
@@ -1165,44 +1242,130 @@ static struct uart_driver cpm_reg = {
1165 .minor = SERIAL_CPM_MINOR, 1242 .minor = SERIAL_CPM_MINOR,
1166 .cons = CPM_UART_CONSOLE, 1243 .cons = CPM_UART_CONSOLE,
1167}; 1244};
1168 1245static int cpm_uart_drv_probe(struct device *dev)
1169static int __init cpm_uart_init(void)
1170{ 1246{
1171 int ret, i; 1247 struct platform_device *pdev = to_platform_device(dev);
1172 1248 struct fs_uart_platform_info *pdata;
1173 printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n"); 1249 int ret = -ENODEV;
1174 1250
1175#ifndef CONFIG_SERIAL_CPM_CONSOLE 1251 if(!pdev) {
1176 ret = cpm_uart_init_portdesc(); 1252 printk(KERN_ERR"CPM UART: platform data missing!\n");
1177 if (ret)
1178 return ret; 1253 return ret;
1179#endif 1254 }
1180 1255
1181 cpm_reg.nr = cpm_uart_nr; 1256 pdata = pdev->dev.platform_data;
1182 ret = uart_register_driver(&cpm_reg); 1257 pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n",
1258 cpm_uart_port_map[pdata->fs_no]);
1183 1259
1184 if (ret) 1260 if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
1185 return ret; 1261 return ret;
1186 1262
1187 for (i = 0; i < cpm_uart_nr; i++) { 1263 if (pdata->init_ioports)
1188 int con = cpm_uart_port_map[i]; 1264 pdata->init_ioports();
1189 cpm_uart_ports[con].port.line = i;
1190 cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
1191 uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
1192 }
1193 1265
1194 return ret; 1266 ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
1267
1268 return ret;
1195} 1269}
1196 1270
1197static void __exit cpm_uart_exit(void) 1271static int cpm_uart_drv_remove(struct device *dev)
1272{
1273 struct platform_device *pdev = to_platform_device(dev);
1274 struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
1275
1276 pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
1277 cpm_uart_port_map[pdata->fs_no]);
1278
1279 uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
1280 return 0;
1281}
1282
1283static struct device_driver cpm_smc_uart_driver = {
1284 .name = "fsl-cpm-smc:uart",
1285 .bus = &platform_bus_type,
1286 .probe = cpm_uart_drv_probe,
1287 .remove = cpm_uart_drv_remove,
1288};
1289
1290static struct device_driver cpm_scc_uart_driver = {
1291 .name = "fsl-cpm-scc:uart",
1292 .bus = &platform_bus_type,
1293 .probe = cpm_uart_drv_probe,
1294 .remove = cpm_uart_drv_remove,
1295};
1296
1297/*
1298 This is supposed to match uart devices on platform bus,
1299 */
1300static int match_is_uart (struct device* dev, void* data)
1198{ 1301{
1302 struct platform_device* pdev = container_of(dev, struct platform_device, dev);
1303 int ret = 0;
1304 /* this was setfunc as uart */
1305 if(strstr(pdev->name,":uart")) {
1306 ret = 1;
1307 }
1308 return ret;
1309}
1310
1311
1312static int cpm_uart_init(void) {
1313
1314 int ret;
1199 int i; 1315 int i;
1316 struct device *dev;
1317 printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");
1318
1319 /* lookup the bus for uart devices */
1320 dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);
1321
1322 /* There are devices on the bus - all should be OK */
1323 if (dev) {
1324 cpm_uart_count();
1325 cpm_reg.nr = cpm_uart_nr;
1326
1327 if (!(ret = uart_register_driver(&cpm_reg))) {
1328 if ((ret = driver_register(&cpm_smc_uart_driver))) {
1329 uart_unregister_driver(&cpm_reg);
1330 return ret;
1331 }
1332 if ((ret = driver_register(&cpm_scc_uart_driver))) {
1333 driver_unregister(&cpm_scc_uart_driver);
1334 uart_unregister_driver(&cpm_reg);
1335 }
1336 }
1337 } else {
1338 /* No capable platform devices found - falling back to legacy mode */
1339 pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");
1340 pr_info(
1341 "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n");
1342#ifndef CONFIG_SERIAL_CPM_CONSOLE
1343 ret = cpm_uart_init_portdesc();
1344 if (ret)
1345 return ret;
1346#endif
1347
1348 cpm_reg.nr = cpm_uart_nr;
1349 ret = uart_register_driver(&cpm_reg);
1350
1351 if (ret)
1352 return ret;
1353
1354 for (i = 0; i < cpm_uart_nr; i++) {
1355 int con = cpm_uart_port_map[i];
1356 cpm_uart_ports[con].port.line = i;
1357 cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
1358 uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
1359 }
1200 1360
1201 for (i = 0; i < cpm_uart_nr; i++) {
1202 int con = cpm_uart_port_map[i];
1203 uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
1204 } 1361 }
1362 return ret;
1363}
1205 1364
1365static void __exit cpm_uart_exit(void)
1366{
1367 driver_unregister(&cpm_scc_uart_driver);
1368 driver_unregister(&cpm_smc_uart_driver);
1206 uart_unregister_driver(&cpm_reg); 1369 uart_unregister_driver(&cpm_reg);
1207} 1370}
1208 1371
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index d789ee55cbb..31223aa862f 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -81,58 +81,11 @@ void cpm_line_cr_cmd(int line, int cmd)
81 81
82void smc1_lineif(struct uart_cpm_port *pinfo) 82void smc1_lineif(struct uart_cpm_port *pinfo)
83{ 83{
84 volatile cpm8xx_t *cp = cpmp;
85
86 (void)cp; /* fix warning */
87#if defined (CONFIG_MPC885ADS)
88 /* Enable SMC1 transceivers */
89 {
90 cp->cp_pepar |= 0x000000c0;
91 cp->cp_pedir &= ~0x000000c0;
92 cp->cp_peso &= ~0x00000040;
93 cp->cp_peso |= 0x00000080;
94 }
95#elif defined (CONFIG_MPC86XADS)
96 unsigned int iobits = 0x000000c0;
97
98 if (!pinfo->is_portb) {
99 cp->cp_pbpar |= iobits;
100 cp->cp_pbdir &= ~iobits;
101 cp->cp_pbodr &= ~iobits;
102 } else {
103 ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
104 ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
105 ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
106 }
107#endif
108 pinfo->brg = 1; 84 pinfo->brg = 1;
109} 85}
110 86
111void smc2_lineif(struct uart_cpm_port *pinfo) 87void smc2_lineif(struct uart_cpm_port *pinfo)
112{ 88{
113 volatile cpm8xx_t *cp = cpmp;
114
115 (void)cp; /* fix warning */
116#if defined (CONFIG_MPC885ADS)
117 cp->cp_pepar |= 0x00000c00;
118 cp->cp_pedir &= ~0x00000c00;
119 cp->cp_peso &= ~0x00000400;
120 cp->cp_peso |= 0x00000800;
121#elif defined (CONFIG_MPC86XADS)
122 unsigned int iobits = 0x00000c00;
123
124 if (!pinfo->is_portb) {
125 cp->cp_pbpar |= iobits;
126 cp->cp_pbdir &= ~iobits;
127 cp->cp_pbodr &= ~iobits;
128 } else {
129 ((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
130 ((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
131 ((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
132 }
133
134#endif
135
136 pinfo->brg = 2; 89 pinfo->brg = 2;
137} 90}
138 91
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index fd9e53ed3fe..c9c3b1d8810 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -142,14 +142,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
142 * be supported in a sane fashion. 142 * be supported in a sane fashion.
143 */ 143 */
144#ifndef CONFIG_STX_GP3 144#ifndef CONFIG_STX_GP3
145#ifdef CONFIG_MPC8560_ADS
146 volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
147 io->iop_ppard |= 0x00000018;
148 io->iop_psord &= ~0x00000008; /* Rx */
149 io->iop_psord &= ~0x00000010; /* Tx */
150 io->iop_pdird &= ~0x00000008; /* Rx */
151 io->iop_pdird |= 0x00000010; /* Tx */
152#else
153 volatile iop_cpm2_t *io = &cpm2_immr->im_ioport; 145 volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
154 io->iop_pparb |= 0x008b0000; 146 io->iop_pparb |= 0x008b0000;
155 io->iop_pdirb |= 0x00880000; 147 io->iop_pdirb |= 0x00880000;
@@ -157,7 +149,6 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
157 io->iop_pdirb &= ~0x00030000; 149 io->iop_pdirb &= ~0x00030000;
158 io->iop_psorb &= ~0x00030000; 150 io->iop_psorb &= ~0x00030000;
159#endif 151#endif
160#endif
161 cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff; 152 cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
162 cpm2_immr->im_cpmux.cmx_scr |= 0x00090000; 153 cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
163 pinfo->brg = 2; 154 pinfo->brg = 2;