blob: 454d77f0469e34b3544c0df16e0ef288c4800cce [file] [log] [blame]
Stefan Reinauereca92fb2006-08-23 14:28:37 +00001/*
Stefan Reinauer7e61e452008-01-18 10:35:56 +00002 * This file is part of the coreboot project.
Stefan Reinauereca92fb2006-08-23 14:28:37 +00003 *
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.
Stefan Reinauereca92fb2006-08-23 14:28:37 +000015 */
16
Uwe Hermannd82baa12006-12-05 14:13:10 +000017/* Pre-RAM driver for SMSC LPC47N217 Super I/O chip. */
18
Stefan Reinauer24d1d4b2013-03-21 11:51:41 -070019#include <arch/io.h>
Stefan Reinauereca92fb2006-08-23 14:28:37 +000020#include <assert.h>
21#include "lpc47n217.h"
22
Edward O'Callaghan85836c22014-07-09 20:26:25 +100023static void pnp_enter_conf_state(pnp_devfn_t dev)
Zheng Bao9db833b2009-12-28 09:59:44 +000024{
Uwe Hermanna69d9782010-11-15 19:35:14 +000025 u16 port = dev >> 8;
Zheng Bao9db833b2009-12-28 09:59:44 +000026 outb(0x55, port);
Stefan Reinauereca92fb2006-08-23 14:28:37 +000027}
28
Edward O'Callaghan85836c22014-07-09 20:26:25 +100029static void pnp_exit_conf_state(pnp_devfn_t dev)
Zheng Bao9db833b2009-12-28 09:59:44 +000030{
Uwe Hermanna69d9782010-11-15 19:35:14 +000031 u16 port = dev >> 8;
Zheng Bao9db833b2009-12-28 09:59:44 +000032 outb(0xaa, port);
Stefan Reinauereca92fb2006-08-23 14:28:37 +000033}
34
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000035/**
36 * Program the base I/O port for the specified logical device.
Zheng Bao9db833b2009-12-28 09:59:44 +000037 *
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000038 * @param dev High 8 bits = Super I/O port, low 8 bits = logical device number.
39 * @param iobase Base I/O port for the logical device.
Zheng Bao9db833b2009-12-28 09:59:44 +000040 */
Edward O'Callaghan85836c22014-07-09 20:26:25 +100041static void lpc47n217_pnp_set_iobase(pnp_devfn_t dev, u16 iobase)
Stefan Reinauereca92fb2006-08-23 14:28:37 +000042{
Uwe Hermanna69d9782010-11-15 19:35:14 +000043 /* LPC47N217 requires base ports to be a multiple of 4. */
Stefan Reinauereca92fb2006-08-23 14:28:37 +000044 ASSERT(!(iobase & 0x3));
45
46 switch(dev & 0xFF) {
Zheng Bao9db833b2009-12-28 09:59:44 +000047 case LPC47N217_PP:
Stefan Reinauereca92fb2006-08-23 14:28:37 +000048 pnp_write_config(dev, 0x23, (iobase >> 2) & 0xff);
49 break;
Zheng Bao9db833b2009-12-28 09:59:44 +000050 case LPC47N217_SP1:
Stefan Reinauereca92fb2006-08-23 14:28:37 +000051 pnp_write_config(dev, 0x24, (iobase >> 2) & 0xff);
52 break;
Stefan Reinauereca92fb2006-08-23 14:28:37 +000053 case LPC47N217_SP2:
54 pnp_write_config(dev, 0x25, (iobase >> 2) & 0xff);
55 break;
Stefan Reinauereca92fb2006-08-23 14:28:37 +000056 default:
57 break;
58 }
59}
60
Uwe Hermannb69cb5a2010-10-26 22:46:43 +000061/**
62 * Enable or disable the specified logical device.
63 *
64 * Technically, a full disable requires setting the device's base I/O port
65 * below 0x100. We don't do that here, because we don't have access to a data
66 * structure that specifies what the 'real' base port is (when asked to enable
67 * the device). Also the function is used only to disable the device while its
68 * true base port is programmed (see lpc47n217_enable_serial() below).
69 *
70 * @param dev High 8 bits = Super I/O port, low 8 bits = logical device number.
71 * @param enable 0 to disable, anythig else to enable.
Zheng Bao9db833b2009-12-28 09:59:44 +000072 */
Edward O'Callaghan85836c22014-07-09 20:26:25 +100073static void lpc47n217_pnp_set_enable(pnp_devfn_t dev, int enable)
Stefan Reinauereca92fb2006-08-23 14:28:37 +000074{
Uwe Hermanna69d9782010-11-15 19:35:14 +000075 u8 power_register = 0, power_mask = 0, current_power, new_power;
Zheng Bao9db833b2009-12-28 09:59:44 +000076
Stefan Reinauereca92fb2006-08-23 14:28:37 +000077 switch(dev & 0xFF) {
Zheng Bao9db833b2009-12-28 09:59:44 +000078 case LPC47N217_PP:
Stefan Reinauereca92fb2006-08-23 14:28:37 +000079 power_register = 0x01;
80 power_mask = 0x04;
81 break;
Zheng Bao9db833b2009-12-28 09:59:44 +000082 case LPC47N217_SP1:
Stefan Reinauereca92fb2006-08-23 14:28:37 +000083 power_register = 0x02;
84 power_mask = 0x08;
85 break;
Stefan Reinauereca92fb2006-08-23 14:28:37 +000086 case LPC47N217_SP2:
87 power_register = 0x02;
88 power_mask = 0x80;
89 break;
Stefan Reinauereca92fb2006-08-23 14:28:37 +000090 default:
91 return;
92 }
93
94 current_power = pnp_read_config(dev, power_register);
Uwe Hermanna69d9782010-11-15 19:35:14 +000095 new_power = current_power & ~power_mask; /* Disable by default. */
Stefan Reinauereca92fb2006-08-23 14:28:37 +000096 if (enable)
Uwe Hermanna69d9782010-11-15 19:35:14 +000097 new_power |= power_mask; /* Enable. */
Stefan Reinauereca92fb2006-08-23 14:28:37 +000098 pnp_write_config(dev, power_register, new_power);
99}
100
Uwe Hermannb69cb5a2010-10-26 22:46:43 +0000101/**
102 * Configure the base I/O port of the specified serial device and enable the
103 * serial device.
104 *
105 * @param dev High 8 bits = Super I/O port, low 8 bits = logical device number.
106 * @param iobase Processor I/O port address to assign to this serial device.
Zheng Bao9db833b2009-12-28 09:59:44 +0000107 */
Antonello Dettoribc839fb2016-03-03 16:25:35 +0000108void lpc47n217_enable_serial(pnp_devfn_t dev, u16 iobase)
Stefan Reinauereca92fb2006-08-23 14:28:37 +0000109{
Uwe Hermannb69cb5a2010-10-26 22:46:43 +0000110 /*
111 * NOTE: Cannot use pnp_set_XXX() here because they assume chip
112 * support for logical devices, which the LPC47N217 doesn't have.
113 */
Stefan Reinauereca92fb2006-08-23 14:28:37 +0000114 pnp_enter_conf_state(dev);
115 lpc47n217_pnp_set_enable(dev, 0);
116 lpc47n217_pnp_set_iobase(dev, iobase);
117 lpc47n217_pnp_set_enable(dev, 1);
118 pnp_exit_conf_state(dev);
119}