Initial revision.
[coreboot.git] / src / superio / smsc / lpc47n217 / lpc47n217_early_serial.c
1 /*\r
2  * $Header: /home/cvs/BIR/ca-cpu/freebios/src/superio/smsc/lpc47n217/lpc47n217_early_serial.c,v 1.1.1.1 2005/07/11 15:28:51 smagnani Exp $\r
3  *\r
4  * lpc47n217_early_serial.c: Pre-RAM driver for SMSC LPC47N217 Super I/O chip\r
5  *\r
6  * Copyright (C) 2005 Digital Design Corporation\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
21  *\r
22  * $Log: lpc47n217_early_serial.c,v $\r
23  * Revision 1.1.1.1  2005/07/11 15:28:51  smagnani\r
24  * Initial revision.\r
25  *\r
26  *\r
27  */\r
28 \r
29 #include <arch/romcc_io.h>\r
30 #include <assert.h>\r
31 #include "lpc47n217.h"\r
32 \r
33 //----------------------------------------------------------------------------------\r
34 // Function:            pnp_enter_conf_state\r
35 // Parameters:          dev - high 8 bits = Super I/O port\r
36 // Return Value:        None\r
37 // Description:         Enable access to the LPC47N217's configuration registers.\r
38 //\r
39 static inline void pnp_enter_conf_state(device_t dev) {\r
40         unsigned port = dev>>8;\r
41     outb(0x55, port);\r
42 }\r
43 \r
44 //----------------------------------------------------------------------------------\r
45 // Function:            pnp_exit_conf_state\r
46 // Parameters:          dev - high 8 bits = Super I/O port\r
47 // Return Value:        None\r
48 // Description:         Disable access to the LPC47N217's configuration registers.\r
49 //\r
50 static void pnp_exit_conf_state(device_t dev) {\r
51         unsigned port = dev>>8;\r
52     outb(0xaa, port);\r
53 }\r
54 \r
55 //----------------------------------------------------------------------------------\r
56 // Function:            lpc47n217_pnp_set_iobase\r
57 // Parameters:          dev - high 8 bits = Super I/O port, \r
58 //                                                low 8 bits = logical device number (per lpc47n217.h)\r
59 //                                      iobase - base I/O port for the logical device\r
60 // Return Value:        None\r
61 // Description:         Program the base I/O port for the specified logical device.\r
62 //\r
63 void lpc47n217_pnp_set_iobase(device_t dev, unsigned iobase)\r
64 {\r
65         // LPC47N217 requires base ports to be a multiple of 4\r
66         ASSERT(!(iobase & 0x3));\r
67 \r
68         switch(dev & 0xFF) {\r
69         case LPC47N217_PP: \r
70                 pnp_write_config(dev, 0x23, (iobase >> 2) & 0xff);\r
71                 break;\r
72                 \r
73         case LPC47N217_SP1: \r
74                 pnp_write_config(dev, 0x24, (iobase >> 2) & 0xff);\r
75                 break;\r
76                 \r
77         case LPC47N217_SP2:\r
78                 pnp_write_config(dev, 0x25, (iobase >> 2) & 0xff);\r
79                 break;\r
80                 \r
81         default:\r
82                 break;\r
83         }\r
84 }\r
85 \r
86 //----------------------------------------------------------------------------------\r
87 // Function:            lpc47n217_pnp_set_enable\r
88 // Parameters:          dev - high 8 bits = Super I/O port, \r
89 //                                                low 8 bits = logical device number (per lpc47n217.h)\r
90 //                                      enable - 0 to disable, anythig else to enable\r
91 // Return Value:        None\r
92 // Description:         Enable or disable the specified logical device.\r
93 //                                      Technically, a full disable requires setting the device's base\r
94 //                                      I/O port below 0x100. We don't do that here, because we don't\r
95 //                                      have access to a data structure that specifies what the 'real'\r
96 //                                      base port is (when asked to enable the device). Also the function\r
97 //                                      is used only to disable the device while its true base port is\r
98 //                                      programmed (see lpc47n217_enable_serial() below).\r
99 //\r
100 void lpc47n217_pnp_set_enable(device_t dev, int enable)\r
101 {\r
102         uint8_t power_register = 0;\r
103         uint8_t power_mask = 0;\r
104         uint8_t current_power;\r
105         uint8_t new_power;\r
106         \r
107         switch(dev & 0xFF) {\r
108         case LPC47N217_PP: \r
109                 power_register = 0x01;\r
110                 power_mask = 0x04;\r
111                 break;\r
112                 \r
113         case LPC47N217_SP1: \r
114                 power_register = 0x02;\r
115                 power_mask = 0x08;\r
116                 break;\r
117                 \r
118         case LPC47N217_SP2:\r
119                 power_register = 0x02;\r
120                 power_mask = 0x80;\r
121                 break;\r
122                 \r
123         default:\r
124                 return;\r
125         }\r
126 \r
127         current_power = pnp_read_config(dev, power_register);\r
128         new_power = current_power & ~power_mask;                // disable by default\r
129 \r
130         if (enable)\r
131                 new_power |= power_mask;                // Enable\r
132 \r
133         pnp_write_config(dev, power_register, new_power);\r
134 }\r
135 \r
136 //----------------------------------------------------------------------------------\r
137 // Function:            lpc47n217_enable_serial\r
138 // Parameters:          dev - high 8 bits = Super I/O port, \r
139 //                                                low 8 bits = logical device number (per lpc47n217.h)\r
140 //                                      iobase - processor I/O port address to assign to this serial device\r
141 // Return Value:        bool\r
142 // Description:         Configure the base I/O port of the specified serial device\r
143 //                                      and enable the serial device.\r
144 //\r
145 static void lpc47n217_enable_serial(device_t dev, unsigned iobase)\r
146 {\r
147         // NOTE: Cannot use pnp_set_XXX() here because they assume chip\r
148         //               support for logical devices, which the LPC47N217 doesn't have\r
149         \r
150         pnp_enter_conf_state(dev);\r
151         lpc47n217_pnp_set_enable(dev, 0);\r
152         lpc47n217_pnp_set_iobase(dev, iobase);\r
153         lpc47n217_pnp_set_enable(dev, 1);\r
154         pnp_exit_conf_state(dev);\r
155 }\r