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