ARM: arm-soc: driver specific changes
A collection of mostly SoC-specific driver updates: - a handful of pincontrol and setup changes - new drivers for hwmon and reset controller for vexpress - timing support updates for OMAP (gpmc and other interfaces) - + a collection of smaller cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQySxPAAoJEIwa5zzehBx3NbgP/iI1EFKI8fK6tp7F1EeTwDYK tKeKFmx+Lio2z5OF0CS0qK0HODtcS2ifJ5Zz3C9VyiRBNDOuYAvDT+5bIAKsKIo3 p0mZyYvgdbcxH30EhYY8klaUVwRyc1noxdO8vENdzoAik4EwUv5zXEKAlcBfScrA usCW0dhGJYKH73kgLKQvsyE9d/aV0hbcniSYoVHH1G4e6U5vG45y8pqeSrTQxfCP nG177/AheoCHoyoh/td0lmkAJsmXM7NpvdJTaAwKgOmEXvOCUwAcuOgOCEuc7sd/ FG3jGLntcB9z0AtbO/YOl3+110o71KBF7gYrDDEjLD6U7zz7yhcmhGVh+FEnVa0I ppgReNN3jZOs7HVlDTvTXLdh5cjZU5JIpLOmHWdERAwkxakDCd07KzPo5g44XTyO CzZuqVFU2JNliIujoJHL2Trnj7Q54fWcgHWkWJdWBhJMsxC42xWgaukCaLDHNuBX Po5cqOnEnAYA0rgvQxfdfPWzJd/NN/kU/ewun0pwni3+PlzhfxFzTRcLcj4BT4By 1S2foQUt0CVkswgFdkRlbGolSsXIlOQmKvsd8kvzldDUzn+0cxgwYHzg4T29hlmY zv0+sfgSxub68zfodDtdyjBWDCgrSHrf3TGjGD/4/X6Bm9Ss3hRj4LHIM7Z2BX7F PJgvGjAZIfuZThLkShLa =CwMf -----END PGP SIGNATURE----- Merge tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc Pull ARM SoC driver specific changes from Olof Johansson: "A collection of mostly SoC-specific driver updates: - a handful of pincontrol and setup changes - new drivers for hwmon and reset controller for vexpress - timing support updates for OMAP (gpmc and other interfaces) - plus a collection of smaller cleanups" * tag 'drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (21 commits) ARM: ux500: fix pin warning ARM: OMAP2+: tusb6010: generic timing calculation ARM: OMAP2+: smc91x: generic timing calculation ARM: OMAP2+: onenand: generic timing calculation ARM: OMAP2+: gpmc: generic timing calculation ARM: OMAP2+: gpmc: handle additional timings ARM: OMAP2+: nand: remove redundant rounding gpio: samsung: use pr_* instead of printk ARM: ux500: fixup magnetometer pins ARM: ux500: add STM pin configuration ARM: ux500: 8500: add pinctrl support for uart1 and uart2 ARM: ux500: cosmetic fixups for uart0 gpio: samsung: Fix input mode setting function for GPIO int ARM: SAMSUNG: Insert bitmap_gpio_int member in samsung_gpio_chip ARM: ux500: 8500: define SDI sleep states ARM: vexpress: Reset driver ARM: ux500: 8500: update SKE keypad pinctrl table hwmon: Versatile Express hwmon driver ARM: ux500: delete duplicate macro ARM: ux500: 8500: add IDLE pin configuration for SPI ...
This commit is contained in:
commit
698d601224
|
@ -0,0 +1,122 @@
|
|||
GPMC (General Purpose Memory Controller):
|
||||
=========================================
|
||||
|
||||
GPMC is an unified memory controller dedicated to interfacing external
|
||||
memory devices like
|
||||
* Asynchronous SRAM like memories and application specific integrated
|
||||
circuit devices.
|
||||
* Asynchronous, synchronous, and page mode burst NOR flash devices
|
||||
NAND flash
|
||||
* Pseudo-SRAM devices
|
||||
|
||||
GPMC is found on Texas Instruments SoC's (OMAP based)
|
||||
IP details: http://www.ti.com/lit/pdf/spruh73 section 7.1
|
||||
|
||||
|
||||
GPMC generic timing calculation:
|
||||
================================
|
||||
|
||||
GPMC has certain timings that has to be programmed for proper
|
||||
functioning of the peripheral, while peripheral has another set of
|
||||
timings. To have peripheral work with gpmc, peripheral timings has to
|
||||
be translated to the form gpmc can understand. The way it has to be
|
||||
translated depends on the connected peripheral. Also there is a
|
||||
dependency for certain gpmc timings on gpmc clock frequency. Hence a
|
||||
generic timing routine was developed to achieve above requirements.
|
||||
|
||||
Generic routine provides a generic method to calculate gpmc timings
|
||||
from gpmc peripheral timings. struct gpmc_device_timings fields has to
|
||||
be updated with timings from the datasheet of the peripheral that is
|
||||
connected to gpmc. A few of the peripheral timings can be fed either
|
||||
in time or in cycles, provision to handle this scenario has been
|
||||
provided (refer struct gpmc_device_timings definition). It may so
|
||||
happen that timing as specified by peripheral datasheet is not present
|
||||
in timing structure, in this scenario, try to correlate peripheral
|
||||
timing to the one available. If that doesn't work, try to add a new
|
||||
field as required by peripheral, educate generic timing routine to
|
||||
handle it, make sure that it does not break any of the existing.
|
||||
Then there may be cases where peripheral datasheet doesn't mention
|
||||
certain fields of struct gpmc_device_timings, zero those entries.
|
||||
|
||||
Generic timing routine has been verified to work properly on
|
||||
multiple onenand's and tusb6010 peripherals.
|
||||
|
||||
A word of caution: generic timing routine has been developed based
|
||||
on understanding of gpmc timings, peripheral timings, available
|
||||
custom timing routines, a kind of reverse engineering without
|
||||
most of the datasheets & hardware (to be exact none of those supported
|
||||
in mainline having custom timing routine) and by simulation.
|
||||
|
||||
gpmc timing dependency on peripheral timings:
|
||||
[<gpmc_timing>: <peripheral timing1>, <peripheral timing2> ...]
|
||||
|
||||
1. common
|
||||
cs_on: t_ceasu
|
||||
adv_on: t_avdasu, t_ceavd
|
||||
|
||||
2. sync common
|
||||
sync_clk: clk
|
||||
page_burst_access: t_bacc
|
||||
clk_activation: t_ces, t_avds
|
||||
|
||||
3. read async muxed
|
||||
adv_rd_off: t_avdp_r
|
||||
oe_on: t_oeasu, t_aavdh
|
||||
access: t_iaa, t_oe, t_ce, t_aa
|
||||
rd_cycle: t_rd_cycle, t_cez_r, t_oez
|
||||
|
||||
4. read async non-muxed
|
||||
adv_rd_off: t_avdp_r
|
||||
oe_on: t_oeasu
|
||||
access: t_iaa, t_oe, t_ce, t_aa
|
||||
rd_cycle: t_rd_cycle, t_cez_r, t_oez
|
||||
|
||||
5. read sync muxed
|
||||
adv_rd_off: t_avdp_r, t_avdh
|
||||
oe_on: t_oeasu, t_ach, cyc_aavdh_oe
|
||||
access: t_iaa, cyc_iaa, cyc_oe
|
||||
rd_cycle: t_cez_r, t_oez, t_ce_rdyz
|
||||
|
||||
6. read sync non-muxed
|
||||
adv_rd_off: t_avdp_r
|
||||
oe_on: t_oeasu
|
||||
access: t_iaa, cyc_iaa, cyc_oe
|
||||
rd_cycle: t_cez_r, t_oez, t_ce_rdyz
|
||||
|
||||
7. write async muxed
|
||||
adv_wr_off: t_avdp_w
|
||||
we_on, wr_data_mux_bus: t_weasu, t_aavdh, cyc_aavhd_we
|
||||
we_off: t_wpl
|
||||
cs_wr_off: t_wph
|
||||
wr_cycle: t_cez_w, t_wr_cycle
|
||||
|
||||
8. write async non-muxed
|
||||
adv_wr_off: t_avdp_w
|
||||
we_on, wr_data_mux_bus: t_weasu
|
||||
we_off: t_wpl
|
||||
cs_wr_off: t_wph
|
||||
wr_cycle: t_cez_w, t_wr_cycle
|
||||
|
||||
9. write sync muxed
|
||||
adv_wr_off: t_avdp_w, t_avdh
|
||||
we_on, wr_data_mux_bus: t_weasu, t_rdyo, t_aavdh, cyc_aavhd_we
|
||||
we_off: t_wpl, cyc_wpl
|
||||
cs_wr_off: t_wph
|
||||
wr_cycle: t_cez_w, t_ce_rdyz
|
||||
|
||||
10. write sync non-muxed
|
||||
adv_wr_off: t_avdp_w
|
||||
we_on, wr_data_mux_bus: t_weasu, t_rdyo
|
||||
we_off: t_wpl, cyc_wpl
|
||||
cs_wr_off: t_wph
|
||||
wr_cycle: t_cez_w, t_ce_rdyz
|
||||
|
||||
|
||||
Note: Many of gpmc timings are dependent on other gpmc timings (a few
|
||||
gpmc timings purely dependent on other gpmc timings, a reason that
|
||||
some of the gpmc timings are missing above), and it will result in
|
||||
indirect dependency of peripheral timings to gpmc timings other than
|
||||
mentioned above, refer timing routine for more details. To know what
|
||||
these peripheral timings correspond to, please see explanations in
|
||||
struct gpmc_device_timings definition. And for gpmc timings refer
|
||||
IP details (link above).
|
|
@ -0,0 +1,23 @@
|
|||
Versatile Express hwmon sensors
|
||||
-------------------------------
|
||||
|
||||
Requires node properties:
|
||||
- "compatible" value : one of
|
||||
"arm,vexpress-volt"
|
||||
"arm,vexpress-amp"
|
||||
"arm,vexpress-temp"
|
||||
"arm,vexpress-power"
|
||||
"arm,vexpress-energy"
|
||||
- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
|
||||
(see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
|
||||
for more details)
|
||||
|
||||
Optional node properties:
|
||||
- label : string describing the monitored value
|
||||
|
||||
Example:
|
||||
energy@0 {
|
||||
compatible = "arm,vexpress-energy";
|
||||
arm,vexpress-sysreg,func = <13 0>;
|
||||
label = "A15 Jcore";
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
Kernel driver vexpress
|
||||
======================
|
||||
|
||||
Supported systems:
|
||||
* ARM Ltd. Versatile Express platform
|
||||
Prefix: 'vexpress'
|
||||
Datasheets:
|
||||
* "Hardware Description" sections of the Technical Reference Manuals
|
||||
for the Versatile Express boards:
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.subset.boards.express/index.html
|
||||
* Section "4.4.14. System Configuration registers" of the V2M-P1 TRM:
|
||||
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0447-/index.html
|
||||
|
||||
Author: Pawel Moll
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Versatile Express platform (http://www.arm.com/versatileexpress/) is a
|
||||
reference & prototyping system for ARM Ltd. processors. It can be set up
|
||||
from a wide range of boards, each of them containing (apart of the main
|
||||
chip/FPGA) a number of microcontrollers responsible for platform
|
||||
configuration and control. Theses microcontrollers can also monitor the
|
||||
board and its environment by a number of internal and external sensors,
|
||||
providing information about power lines voltages and currents, board
|
||||
temperature and power usage. Some of them also calculate consumed energy
|
||||
and provide a cumulative use counter.
|
||||
|
||||
The configuration devices are _not_ memory mapped and must be accessed
|
||||
via a custom interface, abstracted by the "vexpress_config" API.
|
||||
|
||||
As these devices are non-discoverable, they must be described in a Device
|
||||
Tree passed to the kernel. Details of the DT binding for them can be found
|
||||
in Documentation/devicetree/bindings/hwmon/vexpress.txt.
|
|
@ -52,27 +52,27 @@ static int omap2_nand_gpmc_retime(
|
|||
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.sync_clk = gpmc_t->sync_clk;
|
||||
t.cs_on = gpmc_round_ns_to_ticks(gpmc_t->cs_on);
|
||||
t.adv_on = gpmc_round_ns_to_ticks(gpmc_t->adv_on);
|
||||
t.cs_on = gpmc_t->cs_on;
|
||||
t.adv_on = gpmc_t->adv_on;
|
||||
|
||||
/* Read */
|
||||
t.adv_rd_off = gpmc_round_ns_to_ticks(gpmc_t->adv_rd_off);
|
||||
t.adv_rd_off = gpmc_t->adv_rd_off;
|
||||
t.oe_on = t.adv_on;
|
||||
t.access = gpmc_round_ns_to_ticks(gpmc_t->access);
|
||||
t.oe_off = gpmc_round_ns_to_ticks(gpmc_t->oe_off);
|
||||
t.cs_rd_off = gpmc_round_ns_to_ticks(gpmc_t->cs_rd_off);
|
||||
t.rd_cycle = gpmc_round_ns_to_ticks(gpmc_t->rd_cycle);
|
||||
t.access = gpmc_t->access;
|
||||
t.oe_off = gpmc_t->oe_off;
|
||||
t.cs_rd_off = gpmc_t->cs_rd_off;
|
||||
t.rd_cycle = gpmc_t->rd_cycle;
|
||||
|
||||
/* Write */
|
||||
t.adv_wr_off = gpmc_round_ns_to_ticks(gpmc_t->adv_wr_off);
|
||||
t.adv_wr_off = gpmc_t->adv_wr_off;
|
||||
t.we_on = t.oe_on;
|
||||
if (cpu_is_omap34xx()) {
|
||||
t.wr_data_mux_bus = gpmc_round_ns_to_ticks(gpmc_t->wr_data_mux_bus);
|
||||
t.wr_access = gpmc_round_ns_to_ticks(gpmc_t->wr_access);
|
||||
t.wr_data_mux_bus = gpmc_t->wr_data_mux_bus;
|
||||
t.wr_access = gpmc_t->wr_access;
|
||||
}
|
||||
t.we_off = gpmc_round_ns_to_ticks(gpmc_t->we_off);
|
||||
t.cs_wr_off = gpmc_round_ns_to_ticks(gpmc_t->cs_wr_off);
|
||||
t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_t->wr_cycle);
|
||||
t.we_off = gpmc_t->we_off;
|
||||
t.cs_wr_off = gpmc_t->cs_wr_off;
|
||||
t.wr_cycle = gpmc_t->wr_cycle;
|
||||
|
||||
/* Configure GPMC */
|
||||
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
static unsigned onenand_flags;
|
||||
static unsigned latency;
|
||||
static int fclk_offset;
|
||||
|
||||
static struct omap_onenand_platform_data *gpmc_onenand_data;
|
||||
|
||||
|
@ -50,6 +49,7 @@ static struct platform_device gpmc_onenand_device = {
|
|||
|
||||
static struct gpmc_timings omap2_onenand_calc_async_timings(void)
|
||||
{
|
||||
struct gpmc_device_timings dev_t;
|
||||
struct gpmc_timings t;
|
||||
|
||||
const int t_cer = 15;
|
||||
|
@ -59,35 +59,24 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
|
|||
const int t_aa = 76;
|
||||
const int t_oe = 20;
|
||||
const int t_cez = 20; /* max of t_cez, t_oez */
|
||||
const int t_ds = 30;
|
||||
const int t_wpl = 40;
|
||||
const int t_wph = 30;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.sync_clk = 0;
|
||||
t.cs_on = 0;
|
||||
t.adv_on = 0;
|
||||
memset(&dev_t, 0, sizeof(dev_t));
|
||||
|
||||
/* Read */
|
||||
t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer));
|
||||
t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh);
|
||||
t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa);
|
||||
t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce));
|
||||
t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe));
|
||||
t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
|
||||
t.cs_rd_off = t.oe_off;
|
||||
t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez);
|
||||
dev_t.mux = true;
|
||||
dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
|
||||
dev_t.t_avdp_w = dev_t.t_avdp_r;
|
||||
dev_t.t_aavdh = t_aavdh * 1000;
|
||||
dev_t.t_aa = t_aa * 1000;
|
||||
dev_t.t_ce = t_ce * 1000;
|
||||
dev_t.t_oe = t_oe * 1000;
|
||||
dev_t.t_cez_r = t_cez * 1000;
|
||||
dev_t.t_cez_w = dev_t.t_cez_r;
|
||||
dev_t.t_wpl = t_wpl * 1000;
|
||||
dev_t.t_wph = t_wph * 1000;
|
||||
|
||||
/* Write */
|
||||
t.adv_wr_off = t.adv_rd_off;
|
||||
t.we_on = t.oe_on;
|
||||
if (cpu_is_omap34xx()) {
|
||||
t.wr_data_mux_bus = t.we_on;
|
||||
t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
|
||||
}
|
||||
t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
|
||||
t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
|
||||
t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
|
||||
gpmc_calc_timings(&t, &dev_t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -173,18 +162,15 @@ static struct gpmc_timings
|
|||
omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
|
||||
int freq)
|
||||
{
|
||||
struct gpmc_device_timings dev_t;
|
||||
struct gpmc_timings t;
|
||||
const int t_cer = 15;
|
||||
const int t_avdp = 12;
|
||||
const int t_cez = 20; /* max of t_cez, t_oez */
|
||||
const int t_ds = 30;
|
||||
const int t_wpl = 40;
|
||||
const int t_wph = 30;
|
||||
int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
|
||||
u32 reg;
|
||||
int div, fclk_offset_ns, gpmc_clk_ns;
|
||||
int ticks_cez;
|
||||
int cs = cfg->cs;
|
||||
int div, gpmc_clk_ns;
|
||||
|
||||
if (cfg->flags & ONENAND_SYNC_READ)
|
||||
onenand_flags = ONENAND_FLAG_SYNCREAD;
|
||||
|
@ -251,77 +237,35 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
|
|||
latency = 4;
|
||||
|
||||
/* Set synchronous read timings */
|
||||
memset(&t, 0, sizeof(t));
|
||||
memset(&dev_t, 0, sizeof(dev_t));
|
||||
|
||||
if (div == 1) {
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
|
||||
reg |= (1 << 7);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
|
||||
reg |= (1 << 7);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
|
||||
reg |= (1 << 7);
|
||||
reg |= (1 << 23);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
|
||||
} else {
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
|
||||
reg &= ~(1 << 7);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg);
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3);
|
||||
reg &= ~(1 << 7);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg);
|
||||
reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4);
|
||||
reg &= ~(1 << 7);
|
||||
reg &= ~(1 << 23);
|
||||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg);
|
||||
}
|
||||
|
||||
t.sync_clk = min_gpmc_clk_period;
|
||||
t.cs_on = 0;
|
||||
t.adv_on = 0;
|
||||
fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds));
|
||||
fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns);
|
||||
t.page_burst_access = gpmc_clk_ns;
|
||||
|
||||
/* Read */
|
||||
t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
|
||||
t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
|
||||
/* Force at least 1 clk between AVD High to OE Low */
|
||||
if (t.oe_on <= t.adv_rd_off)
|
||||
t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
|
||||
t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
|
||||
t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
|
||||
t.cs_rd_off = t.oe_off;
|
||||
ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div;
|
||||
t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div +
|
||||
ticks_cez);
|
||||
|
||||
/* Write */
|
||||
dev_t.mux = true;
|
||||
dev_t.sync_read = true;
|
||||
if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
|
||||
t.adv_wr_off = t.adv_rd_off;
|
||||
t.we_on = 0;
|
||||
t.we_off = t.cs_rd_off;
|
||||
t.cs_wr_off = t.cs_rd_off;
|
||||
t.wr_cycle = t.rd_cycle;
|
||||
if (cpu_is_omap34xx()) {
|
||||
t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset +
|
||||
gpmc_ps_to_ticks(min_gpmc_clk_period +
|
||||
t_rdyo * 1000));
|
||||
t.wr_access = t.access;
|
||||
}
|
||||
dev_t.sync_write = true;
|
||||
} else {
|
||||
t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int,
|
||||
t_avdp, t_cer));
|
||||
t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh);
|
||||
t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl);
|
||||
t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph);
|
||||
t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez);
|
||||
if (cpu_is_omap34xx()) {
|
||||
t.wr_data_mux_bus = t.we_on;
|
||||
t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds);
|
||||
}
|
||||
dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
|
||||
dev_t.t_wpl = t_wpl * 1000;
|
||||
dev_t.t_wph = t_wph * 1000;
|
||||
dev_t.t_aavdh = t_aavdh * 1000;
|
||||
}
|
||||
dev_t.ce_xdelay = true;
|
||||
dev_t.avd_xdelay = true;
|
||||
dev_t.oe_xdelay = true;
|
||||
dev_t.we_xdelay = true;
|
||||
dev_t.clk = min_gpmc_clk_period;
|
||||
dev_t.t_bacc = dev_t.clk;
|
||||
dev_t.t_ces = t_ces * 1000;
|
||||
dev_t.t_avds = t_avds * 1000;
|
||||
dev_t.t_avdh = t_avdh * 1000;
|
||||
dev_t.t_ach = t_ach * 1000;
|
||||
dev_t.cyc_iaa = (latency + 1);
|
||||
dev_t.t_cez_r = t_cez * 1000;
|
||||
dev_t.t_cez_w = dev_t.t_cez_r;
|
||||
dev_t.cyc_aavdh_oe = 1;
|
||||
dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
|
||||
|
||||
gpmc_calc_timings(&t, &dev_t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
@ -338,7 +282,6 @@ static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
|
|||
(sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
|
||||
(sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
|
||||
(sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
|
||||
GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) |
|
||||
GPMC_CONFIG1_PAGE_LEN(2) |
|
||||
(cpu_is_omap34xx() ? 0 :
|
||||
(GPMC_CONFIG1_WAIT_READ_MON |
|
||||
|
|
|
@ -58,6 +58,7 @@ static struct platform_device gpmc_smc91x_device = {
|
|||
static int smc91c96_gpmc_retime(void)
|
||||
{
|
||||
struct gpmc_timings t;
|
||||
struct gpmc_device_timings dev_t;
|
||||
const int t3 = 10; /* Figure 12.2 read and 12.4 write */
|
||||
const int t4_r = 20; /* Figure 12.2 read */
|
||||
const int t4_w = 5; /* Figure 12.4 write */
|
||||
|
@ -68,32 +69,6 @@ static int smc91c96_gpmc_retime(void)
|
|||
const int t20 = 185; /* Figure 12.2 read and 12.4 write */
|
||||
u32 l;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
/* Read timings */
|
||||
t.cs_on = 0;
|
||||
t.adv_on = t.cs_on;
|
||||
t.oe_on = t.adv_on + t3;
|
||||
t.access = t.oe_on + t5;
|
||||
t.oe_off = t.access;
|
||||
t.adv_rd_off = t.oe_off + max(t4_r, t6);
|
||||
t.cs_rd_off = t.oe_off;
|
||||
t.rd_cycle = t20 - t.oe_on;
|
||||
|
||||
/* Write timings */
|
||||
t.we_on = t.adv_on + t3;
|
||||
|
||||
if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) {
|
||||
t.wr_data_mux_bus = t.we_on;
|
||||
t.we_off = t.wr_data_mux_bus + t7;
|
||||
} else
|
||||
t.we_off = t.we_on + t7;
|
||||
if (cpu_is_omap34xx())
|
||||
t.wr_access = t.we_off;
|
||||
t.adv_wr_off = t.we_off + max(t4_w, t8);
|
||||
t.cs_wr_off = t.we_off + t4_w;
|
||||
t.wr_cycle = t20 - t.we_on;
|
||||
|
||||
l = GPMC_CONFIG1_DEVICESIZE_16;
|
||||
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
|
||||
l |= GPMC_CONFIG1_MUXADDDATA;
|
||||
|
@ -115,6 +90,22 @@ static int smc91c96_gpmc_retime(void)
|
|||
if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
|
||||
return 0;
|
||||
|
||||
memset(&dev_t, 0, sizeof(dev_t));
|
||||
|
||||
dev_t.t_oeasu = t3 * 1000;
|
||||
dev_t.t_oe = t5 * 1000;
|
||||
dev_t.t_cez_r = t4_r * 1000;
|
||||
dev_t.t_oez = t6 * 1000;
|
||||
dev_t.t_rd_cycle = (t20 - t3) * 1000;
|
||||
|
||||
dev_t.t_weasu = t3 * 1000;
|
||||
dev_t.t_wpl = t7 * 1000;
|
||||
dev_t.t_wph = t8 * 1000;
|
||||
dev_t.t_cez_w = t4_w * 1000;
|
||||
dev_t.t_wr_cycle = (t20 - t3) * 1000;
|
||||
|
||||
gpmc_calc_timings(&t, &dev_t);
|
||||
|
||||
return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,13 @@
|
|||
#define GPMC_ECC_CTRL_ECCREG8 0x008
|
||||
#define GPMC_ECC_CTRL_ECCREG9 0x009
|
||||
|
||||
#define GPMC_CONFIG2_CSEXTRADELAY BIT(7)
|
||||
#define GPMC_CONFIG3_ADVEXTRADELAY BIT(7)
|
||||
#define GPMC_CONFIG4_OEEXTRADELAY BIT(7)
|
||||
#define GPMC_CONFIG4_WEEXTRADELAY BIT(23)
|
||||
#define GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN BIT(6)
|
||||
#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN BIT(7)
|
||||
|
||||
#define GPMC_CS0_OFFSET 0x60
|
||||
#define GPMC_CS_SIZE 0x30
|
||||
#define GPMC_BCH_SIZE 0x10
|
||||
|
@ -223,6 +230,51 @@ unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
|
|||
return ticks * gpmc_get_fclk_period() / 1000;
|
||||
}
|
||||
|
||||
static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
|
||||
{
|
||||
return ticks * gpmc_get_fclk_period();
|
||||
}
|
||||
|
||||
static unsigned int gpmc_round_ps_to_ticks(unsigned int time_ps)
|
||||
{
|
||||
unsigned long ticks = gpmc_ps_to_ticks(time_ps);
|
||||
|
||||
return ticks * gpmc_get_fclk_period();
|
||||
}
|
||||
|
||||
static inline void gpmc_cs_modify_reg(int cs, int reg, u32 mask, bool value)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
l = gpmc_cs_read_reg(cs, reg);
|
||||
if (value)
|
||||
l |= mask;
|
||||
else
|
||||
l &= ~mask;
|
||||
gpmc_cs_write_reg(cs, reg, l);
|
||||
}
|
||||
|
||||
static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
|
||||
{
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG1,
|
||||
GPMC_CONFIG1_TIME_PARA_GRAN,
|
||||
p->time_para_granularity);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG2,
|
||||
GPMC_CONFIG2_CSEXTRADELAY, p->cs_extra_delay);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG3,
|
||||
GPMC_CONFIG3_ADVEXTRADELAY, p->adv_extra_delay);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
|
||||
GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
|
||||
GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
|
||||
GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
|
||||
p->cycle2cyclesamecsen);
|
||||
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
|
||||
GPMC_CONFIG6_CYCLE2CYCLEDIFFCSEN,
|
||||
p->cycle2cyclediffcsen);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit,
|
||||
int time, const char *name)
|
||||
|
@ -316,6 +368,12 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
|
|||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access);
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 0, 3, bus_turnaround);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 8, 11, cycle2cycle_delay);
|
||||
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG1, 18, 19, wait_monitoring);
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG1, 25, 26, clk_activation);
|
||||
|
||||
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
|
||||
GPMC_SET_ONE(GPMC_CS_CONFIG6, 16, 19, wr_data_mux_bus);
|
||||
if (gpmc_capability & GPMC_HAS_WR_ACCESS)
|
||||
|
@ -335,6 +393,8 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
|
|||
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, l);
|
||||
}
|
||||
|
||||
gpmc_cs_bool_timings(cs, &t->bool_timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -748,6 +808,319 @@ static int __devinit gpmc_mem_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
|
||||
{
|
||||
u32 temp;
|
||||
int div;
|
||||
|
||||
div = gpmc_calc_divider(sync_clk);
|
||||
temp = gpmc_ps_to_ticks(time_ps);
|
||||
temp = (temp + div - 1) / div;
|
||||
return gpmc_ticks_to_ps(temp * div);
|
||||
}
|
||||
|
||||
/* XXX: can the cycles be avoided ? */
|
||||
static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
bool mux = dev_t->mux;
|
||||
u32 temp;
|
||||
|
||||
/* adv_rd_off */
|
||||
temp = dev_t->t_avdp_r;
|
||||
/* XXX: mux check required ? */
|
||||
if (mux) {
|
||||
/* XXX: t_avdp not to be required for sync, only added for tusb
|
||||
* this indirectly necessitates requirement of t_avdp_r and
|
||||
* t_avdp_w instead of having a single t_avdp
|
||||
*/
|
||||
temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_avdh);
|
||||
temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
|
||||
}
|
||||
gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* oe_on */
|
||||
temp = dev_t->t_oeasu; /* XXX: remove this ? */
|
||||
if (mux) {
|
||||
temp = max_t(u32, temp, gpmc_t->clk_activation + dev_t->t_ach);
|
||||
temp = max_t(u32, temp, gpmc_t->adv_rd_off +
|
||||
gpmc_ticks_to_ps(dev_t->cyc_aavdh_oe));
|
||||
}
|
||||
gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* access */
|
||||
/* XXX: any scope for improvement ?, by combining oe_on
|
||||
* and clk_activation, need to check whether
|
||||
* access = clk_activation + round to sync clk ?
|
||||
*/
|
||||
temp = max_t(u32, dev_t->t_iaa, dev_t->cyc_iaa * gpmc_t->sync_clk);
|
||||
temp += gpmc_t->clk_activation;
|
||||
if (dev_t->cyc_oe)
|
||||
temp = max_t(u32, temp, gpmc_t->oe_on +
|
||||
gpmc_ticks_to_ps(dev_t->cyc_oe));
|
||||
gpmc_t->access = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
|
||||
gpmc_t->cs_rd_off = gpmc_t->oe_off;
|
||||
|
||||
/* rd_cycle */
|
||||
temp = max_t(u32, dev_t->t_cez_r, dev_t->t_oez);
|
||||
temp = gpmc_round_ps_to_sync_clk(temp, gpmc_t->sync_clk) +
|
||||
gpmc_t->access;
|
||||
/* XXX: barter t_ce_rdyz with t_cez_r ? */
|
||||
if (dev_t->t_ce_rdyz)
|
||||
temp = max_t(u32, temp, gpmc_t->cs_rd_off + dev_t->t_ce_rdyz);
|
||||
gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
bool mux = dev_t->mux;
|
||||
u32 temp;
|
||||
|
||||
/* adv_wr_off */
|
||||
temp = dev_t->t_avdp_w;
|
||||
if (mux) {
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->clk_activation + dev_t->t_avdh);
|
||||
temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
|
||||
}
|
||||
gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* wr_data_mux_bus */
|
||||
temp = max_t(u32, dev_t->t_weasu,
|
||||
gpmc_t->clk_activation + dev_t->t_rdyo);
|
||||
/* XXX: shouldn't mux be kept as a whole for wr_data_mux_bus ?,
|
||||
* and in that case remember to handle we_on properly
|
||||
*/
|
||||
if (mux) {
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->adv_wr_off + dev_t->t_aavdh);
|
||||
temp = max_t(u32, temp, gpmc_t->adv_wr_off +
|
||||
gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
|
||||
}
|
||||
gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* we_on */
|
||||
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
|
||||
gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
|
||||
else
|
||||
gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
|
||||
|
||||
/* wr_access */
|
||||
/* XXX: gpmc_capability check reqd ? , even if not, will not harm */
|
||||
gpmc_t->wr_access = gpmc_t->access;
|
||||
|
||||
/* we_off */
|
||||
temp = gpmc_t->we_on + dev_t->t_wpl;
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->wr_access + gpmc_ticks_to_ps(1));
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->we_on + gpmc_ticks_to_ps(dev_t->cyc_wpl));
|
||||
gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
|
||||
dev_t->t_wph);
|
||||
|
||||
/* wr_cycle */
|
||||
temp = gpmc_round_ps_to_sync_clk(dev_t->t_cez_w, gpmc_t->sync_clk);
|
||||
temp += gpmc_t->wr_access;
|
||||
/* XXX: barter t_ce_rdyz with t_cez_w ? */
|
||||
if (dev_t->t_ce_rdyz)
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->cs_wr_off + dev_t->t_ce_rdyz);
|
||||
gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
bool mux = dev_t->mux;
|
||||
u32 temp;
|
||||
|
||||
/* adv_rd_off */
|
||||
temp = dev_t->t_avdp_r;
|
||||
if (mux)
|
||||
temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
|
||||
gpmc_t->adv_rd_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* oe_on */
|
||||
temp = dev_t->t_oeasu;
|
||||
if (mux)
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->adv_rd_off + dev_t->t_aavdh);
|
||||
gpmc_t->oe_on = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* access */
|
||||
temp = max_t(u32, dev_t->t_iaa, /* XXX: remove t_iaa in async ? */
|
||||
gpmc_t->oe_on + dev_t->t_oe);
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->cs_on + dev_t->t_ce);
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->adv_on + dev_t->t_aa);
|
||||
gpmc_t->access = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
gpmc_t->oe_off = gpmc_t->access + gpmc_ticks_to_ps(1);
|
||||
gpmc_t->cs_rd_off = gpmc_t->oe_off;
|
||||
|
||||
/* rd_cycle */
|
||||
temp = max_t(u32, dev_t->t_rd_cycle,
|
||||
gpmc_t->cs_rd_off + dev_t->t_cez_r);
|
||||
temp = max_t(u32, temp, gpmc_t->oe_off + dev_t->t_oez);
|
||||
gpmc_t->rd_cycle = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
bool mux = dev_t->mux;
|
||||
u32 temp;
|
||||
|
||||
/* adv_wr_off */
|
||||
temp = dev_t->t_avdp_w;
|
||||
if (mux)
|
||||
temp = max_t(u32, gpmc_t->adv_on + gpmc_ticks_to_ps(1), temp);
|
||||
gpmc_t->adv_wr_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* wr_data_mux_bus */
|
||||
temp = dev_t->t_weasu;
|
||||
if (mux) {
|
||||
temp = max_t(u32, temp, gpmc_t->adv_wr_off + dev_t->t_aavdh);
|
||||
temp = max_t(u32, temp, gpmc_t->adv_wr_off +
|
||||
gpmc_ticks_to_ps(dev_t->cyc_aavdh_we));
|
||||
}
|
||||
gpmc_t->wr_data_mux_bus = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
/* we_on */
|
||||
if (gpmc_capability & GPMC_HAS_WR_DATA_MUX_BUS)
|
||||
gpmc_t->we_on = gpmc_round_ps_to_ticks(dev_t->t_weasu);
|
||||
else
|
||||
gpmc_t->we_on = gpmc_t->wr_data_mux_bus;
|
||||
|
||||
/* we_off */
|
||||
temp = gpmc_t->we_on + dev_t->t_wpl;
|
||||
gpmc_t->we_off = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
gpmc_t->cs_wr_off = gpmc_round_ps_to_ticks(gpmc_t->we_off +
|
||||
dev_t->t_wph);
|
||||
|
||||
/* wr_cycle */
|
||||
temp = max_t(u32, dev_t->t_wr_cycle,
|
||||
gpmc_t->cs_wr_off + dev_t->t_cez_w);
|
||||
gpmc_t->wr_cycle = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
gpmc_t->sync_clk = gpmc_calc_divider(dev_t->clk) *
|
||||
gpmc_get_fclk_period();
|
||||
|
||||
gpmc_t->page_burst_access = gpmc_round_ps_to_sync_clk(
|
||||
dev_t->t_bacc,
|
||||
gpmc_t->sync_clk);
|
||||
|
||||
temp = max_t(u32, dev_t->t_ces, dev_t->t_avds);
|
||||
gpmc_t->clk_activation = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
if (gpmc_calc_divider(gpmc_t->sync_clk) != 1)
|
||||
return 0;
|
||||
|
||||
if (dev_t->ce_xdelay)
|
||||
gpmc_t->bool_timings.cs_extra_delay = true;
|
||||
if (dev_t->avd_xdelay)
|
||||
gpmc_t->bool_timings.adv_extra_delay = true;
|
||||
if (dev_t->oe_xdelay)
|
||||
gpmc_t->bool_timings.oe_extra_delay = true;
|
||||
if (dev_t->we_xdelay)
|
||||
gpmc_t->bool_timings.we_extra_delay = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
/* cs_on */
|
||||
gpmc_t->cs_on = gpmc_round_ps_to_ticks(dev_t->t_ceasu);
|
||||
|
||||
/* adv_on */
|
||||
temp = dev_t->t_avdasu;
|
||||
if (dev_t->t_ce_avd)
|
||||
temp = max_t(u32, temp,
|
||||
gpmc_t->cs_on + dev_t->t_ce_avd);
|
||||
gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
|
||||
|
||||
if (dev_t->sync_write || dev_t->sync_read)
|
||||
gpmc_calc_sync_common_timings(gpmc_t, dev_t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: remove this function once all peripherals are confirmed to
|
||||
* work with generic timing. Simultaneously gpmc_cs_set_timings()
|
||||
* has to be modified to handle timings in ps instead of ns
|
||||
*/
|
||||
static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
|
||||
{
|
||||
t->cs_on /= 1000;
|
||||
t->cs_rd_off /= 1000;
|
||||
t->cs_wr_off /= 1000;
|
||||
t->adv_on /= 1000;
|
||||
t->adv_rd_off /= 1000;
|
||||
t->adv_wr_off /= 1000;
|
||||
t->we_on /= 1000;
|
||||
t->we_off /= 1000;
|
||||
t->oe_on /= 1000;
|
||||
t->oe_off /= 1000;
|
||||
t->page_burst_access /= 1000;
|
||||
t->access /= 1000;
|
||||
t->rd_cycle /= 1000;
|
||||
t->wr_cycle /= 1000;
|
||||
t->bus_turnaround /= 1000;
|
||||
t->cycle2cycle_delay /= 1000;
|
||||
t->wait_monitoring /= 1000;
|
||||
t->clk_activation /= 1000;
|
||||
t->wr_access /= 1000;
|
||||
t->wr_data_mux_bus /= 1000;
|
||||
}
|
||||
|
||||
int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t)
|
||||
{
|
||||
memset(gpmc_t, 0, sizeof(*gpmc_t));
|
||||
|
||||
gpmc_calc_common_timings(gpmc_t, dev_t);
|
||||
|
||||
if (dev_t->sync_read)
|
||||
gpmc_calc_sync_read_timings(gpmc_t, dev_t);
|
||||
else
|
||||
gpmc_calc_async_read_timings(gpmc_t, dev_t);
|
||||
|
||||
if (dev_t->sync_write)
|
||||
gpmc_calc_sync_write_timings(gpmc_t, dev_t);
|
||||
else
|
||||
gpmc_calc_async_write_timings(gpmc_t, dev_t);
|
||||
|
||||
/* TODO: remove, see function definition */
|
||||
gpmc_convert_ps_to_ns(gpmc_t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devinit int gpmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
int rc;
|
||||
|
|
|
@ -74,6 +74,17 @@
|
|||
#define GPMC_IRQ_COUNT_EVENT 0x02
|
||||
|
||||
|
||||
/* bool type time settings */
|
||||
struct gpmc_bool_timings {
|
||||
bool cycle2cyclediffcsen;
|
||||
bool cycle2cyclesamecsen;
|
||||
bool we_extra_delay;
|
||||
bool oe_extra_delay;
|
||||
bool adv_extra_delay;
|
||||
bool cs_extra_delay;
|
||||
bool time_para_granularity;
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that all values in this struct are in nanoseconds except sync_clk
|
||||
* (which is in picoseconds), while the register values are in gpmc_fck cycles.
|
||||
|
@ -83,34 +94,104 @@ struct gpmc_timings {
|
|||
u32 sync_clk;
|
||||
|
||||
/* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */
|
||||
u16 cs_on; /* Assertion time */
|
||||
u16 cs_rd_off; /* Read deassertion time */
|
||||
u16 cs_wr_off; /* Write deassertion time */
|
||||
u32 cs_on; /* Assertion time */
|
||||
u32 cs_rd_off; /* Read deassertion time */
|
||||
u32 cs_wr_off; /* Write deassertion time */
|
||||
|
||||
/* ADV signal timings corresponding to GPMC_CONFIG3 */
|
||||
u16 adv_on; /* Assertion time */
|
||||
u16 adv_rd_off; /* Read deassertion time */
|
||||
u16 adv_wr_off; /* Write deassertion time */
|
||||
u32 adv_on; /* Assertion time */
|
||||
u32 adv_rd_off; /* Read deassertion time */
|
||||
u32 adv_wr_off; /* Write deassertion time */
|
||||
|
||||
/* WE signals timings corresponding to GPMC_CONFIG4 */
|
||||
u16 we_on; /* WE assertion time */
|
||||
u16 we_off; /* WE deassertion time */
|
||||
u32 we_on; /* WE assertion time */
|
||||
u32 we_off; /* WE deassertion time */
|
||||
|
||||
/* OE signals timings corresponding to GPMC_CONFIG4 */
|
||||
u16 oe_on; /* OE assertion time */
|
||||
u16 oe_off; /* OE deassertion time */
|
||||
u32 oe_on; /* OE assertion time */
|
||||
u32 oe_off; /* OE deassertion time */
|
||||
|
||||
/* Access time and cycle time timings corresponding to GPMC_CONFIG5 */
|
||||
u16 page_burst_access; /* Multiple access word delay */
|
||||
u16 access; /* Start-cycle to first data valid delay */
|
||||
u16 rd_cycle; /* Total read cycle time */
|
||||
u16 wr_cycle; /* Total write cycle time */
|
||||
u32 page_burst_access; /* Multiple access word delay */
|
||||
u32 access; /* Start-cycle to first data valid delay */
|
||||
u32 rd_cycle; /* Total read cycle time */
|
||||
u32 wr_cycle; /* Total write cycle time */
|
||||
|
||||
u32 bus_turnaround;
|
||||
u32 cycle2cycle_delay;
|
||||
|
||||
u32 wait_monitoring;
|
||||
u32 clk_activation;
|
||||
|
||||
/* The following are only on OMAP3430 */
|
||||
u16 wr_access; /* WRACCESSTIME */
|
||||
u16 wr_data_mux_bus; /* WRDATAONADMUXBUS */
|
||||
u32 wr_access; /* WRACCESSTIME */
|
||||
u32 wr_data_mux_bus; /* WRDATAONADMUXBUS */
|
||||
|
||||
struct gpmc_bool_timings bool_timings;
|
||||
};
|
||||
|
||||
/* Device timings in picoseconds */
|
||||
struct gpmc_device_timings {
|
||||
u32 t_ceasu; /* address setup to CS valid */
|
||||
u32 t_avdasu; /* address setup to ADV valid */
|
||||
/* XXX: try to combine t_avdp_r & t_avdp_w. Issue is
|
||||
* of tusb using these timings even for sync whilst
|
||||
* ideally for adv_rd/(wr)_off it should have considered
|
||||
* t_avdh instead. This indirectly necessitates r/w
|
||||
* variations of t_avdp as it is possible to have one
|
||||
* sync & other async
|
||||
*/
|
||||
u32 t_avdp_r; /* ADV low time (what about t_cer ?) */
|
||||
u32 t_avdp_w;
|
||||
u32 t_aavdh; /* address hold time */
|
||||
u32 t_oeasu; /* address setup to OE valid */
|
||||
u32 t_aa; /* access time from ADV assertion */
|
||||
u32 t_iaa; /* initial access time */
|
||||
u32 t_oe; /* access time from OE assertion */
|
||||
u32 t_ce; /* access time from CS asertion */
|
||||
u32 t_rd_cycle; /* read cycle time */
|
||||
u32 t_cez_r; /* read CS deassertion to high Z */
|
||||
u32 t_cez_w; /* write CS deassertion to high Z */
|
||||
u32 t_oez; /* OE deassertion to high Z */
|
||||
u32 t_weasu; /* address setup to WE valid */
|
||||
u32 t_wpl; /* write assertion time */
|
||||
u32 t_wph; /* write deassertion time */
|
||||
u32 t_wr_cycle; /* write cycle time */
|
||||
|
||||
u32 clk;
|
||||
u32 t_bacc; /* burst access valid clock to output delay */
|
||||
u32 t_ces; /* CS setup time to clk */
|
||||
u32 t_avds; /* ADV setup time to clk */
|
||||
u32 t_avdh; /* ADV hold time from clk */
|
||||
u32 t_ach; /* address hold time from clk */
|
||||
u32 t_rdyo; /* clk to ready valid */
|
||||
|
||||
u32 t_ce_rdyz; /* XXX: description ?, or use t_cez instead */
|
||||
u32 t_ce_avd; /* CS on to ADV on delay */
|
||||
|
||||
/* XXX: check the possibility of combining
|
||||
* cyc_aavhd_oe & cyc_aavdh_we
|
||||
*/
|
||||
u8 cyc_aavdh_oe;/* read address hold time in cycles */
|
||||
u8 cyc_aavdh_we;/* write address hold time in cycles */
|
||||
u8 cyc_oe; /* access time from OE assertion in cycles */
|
||||
u8 cyc_wpl; /* write deassertion time in cycles */
|
||||
u32 cyc_iaa; /* initial access time in cycles */
|
||||
|
||||
bool mux; /* address & data muxed */
|
||||
bool sync_write;/* synchronous write */
|
||||
bool sync_read; /* synchronous read */
|
||||
|
||||
/* extra delays */
|
||||
bool ce_xdelay;
|
||||
bool avd_xdelay;
|
||||
bool oe_xdelay;
|
||||
bool we_xdelay;
|
||||
};
|
||||
|
||||
extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
|
||||
struct gpmc_device_timings *dev_t);
|
||||
|
||||
extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
|
||||
extern int gpmc_get_client_irq(unsigned irq_config);
|
||||
|
||||
|
|
|
@ -27,180 +27,88 @@ static u8 async_cs, sync_cs;
|
|||
static unsigned refclk_psec;
|
||||
|
||||
|
||||
/* t2_ps, when quantized to fclk units, must happen no earlier than
|
||||
* the clock after after t1_NS.
|
||||
*
|
||||
* Return a possibly updated value of t2_ps, converted to nsec.
|
||||
*/
|
||||
static unsigned
|
||||
next_clk(unsigned t1_NS, unsigned t2_ps, unsigned fclk_ps)
|
||||
{
|
||||
unsigned t1_ps = t1_NS * 1000;
|
||||
unsigned t1_f, t2_f;
|
||||
|
||||
if ((t1_ps + fclk_ps) < t2_ps)
|
||||
return t2_ps / 1000;
|
||||
|
||||
t1_f = (t1_ps + fclk_ps - 1) / fclk_ps;
|
||||
t2_f = (t2_ps + fclk_ps - 1) / fclk_ps;
|
||||
|
||||
if (t1_f >= t2_f)
|
||||
t2_f = t1_f + 1;
|
||||
|
||||
return (t2_f * fclk_ps) / 1000;
|
||||
}
|
||||
|
||||
/* NOTE: timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
|
||||
|
||||
static int tusb_set_async_mode(unsigned sysclk_ps, unsigned fclk_ps)
|
||||
static int tusb_set_async_mode(unsigned sysclk_ps)
|
||||
{
|
||||
struct gpmc_device_timings dev_t;
|
||||
struct gpmc_timings t;
|
||||
unsigned t_acsnh_advnh = sysclk_ps + 3000;
|
||||
unsigned tmp;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
memset(&dev_t, 0, sizeof(dev_t));
|
||||
|
||||
/* CS_ON = t_acsnh_acsnl */
|
||||
t.cs_on = 8;
|
||||
/* ADV_ON = t_acsnh_advnh - t_advn */
|
||||
t.adv_on = next_clk(t.cs_on, t_acsnh_advnh - 7000, fclk_ps);
|
||||
dev_t.mux = true;
|
||||
|
||||
/*
|
||||
* READ ... from omap2420 TRM fig 12-13
|
||||
*/
|
||||
dev_t.t_ceasu = 8 * 1000;
|
||||
dev_t.t_avdasu = t_acsnh_advnh - 7000;
|
||||
dev_t.t_ce_avd = 1000;
|
||||
dev_t.t_avdp_r = t_acsnh_advnh;
|
||||
dev_t.t_oeasu = t_acsnh_advnh + 1000;
|
||||
dev_t.t_oe = 300;
|
||||
dev_t.t_cez_r = 7000;
|
||||
dev_t.t_cez_w = dev_t.t_cez_r;
|
||||
dev_t.t_avdp_w = t_acsnh_advnh;
|
||||
dev_t.t_weasu = t_acsnh_advnh + 1000;
|
||||
dev_t.t_wpl = 300;
|
||||
dev_t.cyc_aavdh_we = 1;
|
||||
|
||||
/* ADV_RD_OFF = t_acsnh_advnh */
|
||||
t.adv_rd_off = next_clk(t.adv_on, t_acsnh_advnh, fclk_ps);
|
||||
|
||||
/* OE_ON = t_acsnh_advnh + t_advn_oen (then wait for nRDY) */
|
||||
t.oe_on = next_clk(t.adv_on, t_acsnh_advnh + 1000, fclk_ps);
|
||||
|
||||
/* ACCESS = counters continue only after nRDY */
|
||||
tmp = t.oe_on * 1000 + 300;
|
||||
t.access = next_clk(t.oe_on, tmp, fclk_ps);
|
||||
|
||||
/* OE_OFF = after data gets sampled */
|
||||
tmp = t.access * 1000;
|
||||
t.oe_off = next_clk(t.access, tmp, fclk_ps);
|
||||
|
||||
t.cs_rd_off = t.oe_off;
|
||||
|
||||
tmp = t.cs_rd_off * 1000 + 7000 /* t_acsn_rdy_z */;
|
||||
t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
|
||||
|
||||
/*
|
||||
* WRITE ... from omap2420 TRM fig 12-15
|
||||
*/
|
||||
|
||||
/* ADV_WR_OFF = t_acsnh_advnh */
|
||||
t.adv_wr_off = t.adv_rd_off;
|
||||
|
||||
/* WE_ON = t_acsnh_advnh + t_advn_wen (then wait for nRDY) */
|
||||
t.we_on = next_clk(t.adv_wr_off, t_acsnh_advnh + 1000, fclk_ps);
|
||||
|
||||
/* WE_OFF = after data gets sampled */
|
||||
tmp = t.we_on * 1000 + 300;
|
||||
t.we_off = next_clk(t.we_on, tmp, fclk_ps);
|
||||
|
||||
t.cs_wr_off = t.we_off;
|
||||
|
||||
tmp = t.cs_wr_off * 1000 + 7000 /* t_acsn_rdy_z */;
|
||||
t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
|
||||
gpmc_calc_timings(&t, &dev_t);
|
||||
|
||||
return gpmc_cs_set_timings(async_cs, &t);
|
||||
}
|
||||
|
||||
static int tusb_set_sync_mode(unsigned sysclk_ps, unsigned fclk_ps)
|
||||
static int tusb_set_sync_mode(unsigned sysclk_ps)
|
||||
{
|
||||
struct gpmc_device_timings dev_t;
|
||||
struct gpmc_timings t;
|
||||
unsigned t_scsnh_advnh = sysclk_ps + 3000;
|
||||
unsigned tmp;
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
t.cs_on = 8;
|
||||
memset(&dev_t, 0, sizeof(dev_t));
|
||||
|
||||
/* ADV_ON = t_acsnh_advnh - t_advn */
|
||||
t.adv_on = next_clk(t.cs_on, t_scsnh_advnh - 7000, fclk_ps);
|
||||
dev_t.mux = true;
|
||||
dev_t.sync_read = true;
|
||||
dev_t.sync_write = true;
|
||||
|
||||
/* GPMC_CLK rate = fclk rate / div */
|
||||
t.sync_clk = 11100 /* 11.1 nsec */;
|
||||
tmp = (t.sync_clk + fclk_ps - 1) / fclk_ps;
|
||||
if (tmp > 4)
|
||||
return -ERANGE;
|
||||
if (tmp == 0)
|
||||
tmp = 1;
|
||||
t.page_burst_access = (fclk_ps * tmp) / 1000;
|
||||
dev_t.clk = 11100;
|
||||
dev_t.t_bacc = 1000;
|
||||
dev_t.t_ces = 1000;
|
||||
dev_t.t_ceasu = 8 * 1000;
|
||||
dev_t.t_avdasu = t_scsnh_advnh - 7000;
|
||||
dev_t.t_ce_avd = 1000;
|
||||
dev_t.t_avdp_r = t_scsnh_advnh;
|
||||
dev_t.cyc_aavdh_oe = 3;
|
||||
dev_t.cyc_oe = 5;
|
||||
dev_t.t_ce_rdyz = 7000;
|
||||
dev_t.t_avdp_w = t_scsnh_advnh;
|
||||
dev_t.cyc_aavdh_we = 3;
|
||||
dev_t.cyc_wpl = 6;
|
||||
dev_t.t_ce_rdyz = 7000;
|
||||
|
||||
/*
|
||||
* READ ... based on omap2420 TRM fig 12-19, 12-20
|
||||
*/
|
||||
|
||||
/* ADV_RD_OFF = t_scsnh_advnh */
|
||||
t.adv_rd_off = next_clk(t.adv_on, t_scsnh_advnh, fclk_ps);
|
||||
|
||||
/* OE_ON = t_scsnh_advnh + t_advn_oen * fclk_ps (then wait for nRDY) */
|
||||
tmp = (t.adv_rd_off * 1000) + (3 * fclk_ps);
|
||||
t.oe_on = next_clk(t.adv_on, tmp, fclk_ps);
|
||||
|
||||
/* ACCESS = number of clock cycles after t_adv_eon */
|
||||
tmp = (t.oe_on * 1000) + (5 * fclk_ps);
|
||||
t.access = next_clk(t.oe_on, tmp, fclk_ps);
|
||||
|
||||
/* OE_OFF = after data gets sampled */
|
||||
tmp = (t.access * 1000) + (1 * fclk_ps);
|
||||
t.oe_off = next_clk(t.access, tmp, fclk_ps);
|
||||
|
||||
t.cs_rd_off = t.oe_off;
|
||||
|
||||
tmp = t.cs_rd_off * 1000 + 7000 /* t_scsn_rdy_z */;
|
||||
t.rd_cycle = next_clk(t.cs_rd_off, tmp, fclk_ps);
|
||||
|
||||
/*
|
||||
* WRITE ... based on omap2420 TRM fig 12-21
|
||||
*/
|
||||
|
||||
/* ADV_WR_OFF = t_scsnh_advnh */
|
||||
t.adv_wr_off = t.adv_rd_off;
|
||||
|
||||
/* WE_ON = t_scsnh_advnh + t_advn_wen * fclk_ps (then wait for nRDY) */
|
||||
tmp = (t.adv_wr_off * 1000) + (3 * fclk_ps);
|
||||
t.we_on = next_clk(t.adv_wr_off, tmp, fclk_ps);
|
||||
|
||||
/* WE_OFF = number of clock cycles after t_adv_wen */
|
||||
tmp = (t.we_on * 1000) + (6 * fclk_ps);
|
||||
t.we_off = next_clk(t.we_on, tmp, fclk_ps);
|
||||
|
||||
t.cs_wr_off = t.we_off;
|
||||
|
||||
tmp = t.cs_wr_off * 1000 + 7000 /* t_scsn_rdy_z */;
|
||||
t.wr_cycle = next_clk(t.cs_wr_off, tmp, fclk_ps);
|
||||
gpmc_calc_timings(&t, &dev_t);
|
||||
|
||||
return gpmc_cs_set_timings(sync_cs, &t);
|
||||
}
|
||||
|
||||
extern unsigned long gpmc_get_fclk_period(void);
|
||||
|
||||
/* tusb driver calls this when it changes the chip's clocking */
|
||||
int tusb6010_platform_retime(unsigned is_refclk)
|
||||
{
|
||||
static const char error[] =
|
||||
KERN_ERR "tusb6010 %s retime error %d\n";
|
||||
|
||||
unsigned fclk_ps = gpmc_get_fclk_period();
|
||||
unsigned sysclk_ps;
|
||||
int status;
|
||||
|
||||
if (!refclk_psec || fclk_ps == 0)
|
||||
if (!refclk_psec)
|
||||
return -ENODEV;
|
||||
|
||||
sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
|
||||
|
||||
status = tusb_set_async_mode(sysclk_ps, fclk_ps);
|
||||
status = tusb_set_async_mode(sysclk_ps);
|
||||
if (status < 0) {
|
||||
printk(error, "async", status);
|
||||
goto done;
|
||||
}
|
||||
status = tusb_set_sync_mode(sysclk_ps, fclk_ps);
|
||||
status = tusb_set_sync_mode(sysclk_ps);
|
||||
if (status < 0)
|
||||
printk(error, "sync", status);
|
||||
done:
|
||||
|
@ -284,7 +192,6 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
|
|||
| GPMC_CONFIG1_READTYPE_SYNC
|
||||
| GPMC_CONFIG1_WRITEMULTIPLE_SUPP
|
||||
| GPMC_CONFIG1_WRITETYPE_SYNC
|
||||
| GPMC_CONFIG1_CLKACTIVATIONTIME(1)
|
||||
| GPMC_CONFIG1_PAGE_LEN(2)
|
||||
| GPMC_CONFIG1_WAIT_READ_MON
|
||||
| GPMC_CONFIG1_WAIT_WRITE_MON
|
||||
|
|
|
@ -33,8 +33,6 @@ BIAS(in_nopull, PIN_INPUT_NOPULL);
|
|||
BIAS(in_nopull_slpm_nowkup, PIN_INPUT_NOPULL|PIN_SLPM_WAKEUP_DISABLE);
|
||||
BIAS(in_pu, PIN_INPUT_PULLUP);
|
||||
BIAS(in_pd, PIN_INPUT_PULLDOWN);
|
||||
BIAS(in_pd_slpm_in_pu, PIN_INPUT_PULLDOWN|PIN_SLPM_INPUT_PULLUP);
|
||||
BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
|
||||
BIAS(out_hi, PIN_OUTPUT_HIGH);
|
||||
BIAS(out_lo, PIN_OUTPUT_LOW);
|
||||
BIAS(out_lo_slpm_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
|
||||
|
@ -46,14 +44,34 @@ BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SL
|
|||
BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
|
||||
BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
|
||||
/* Sleep modes */
|
||||
BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
|
||||
BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
|
||||
BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
|
||||
BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_lo_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE);
|
||||
BIAS(slpm_out_lo_wkup_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_out_hi_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_OUTPUT_HIGH|
|
||||
PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_INPUT_NOPULL|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(slpm_in_pu_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_PULLUP|
|
||||
PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
|
||||
BIAS(slpm_out_wkup_pdis, PIN_SLEEPMODE_ENABLED|
|
||||
PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(out_lo_wkup_pdis, PIN_SLPM_OUTPUT_LOW|
|
||||
PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(in_wkup_pdis_en, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
|
||||
PIN_SLPM_PDIS_ENABLED);
|
||||
BIAS(in_wkup_pdis, PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|
|
||||
PIN_SLPM_PDIS_DISABLED);
|
||||
BIAS(out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|
|
||||
PIN_SLPM_PDIS_DISABLED);
|
||||
|
||||
/* We use these to define hog settings that are always done on boot */
|
||||
#define DB8500_MUX_HOG(group,func) \
|
||||
|
@ -69,13 +87,16 @@ BIAS(slpm_in_nopull_wkup_pdis, PIN_SLEEPMODE_ENABLED|PIN_SLPM_INPUT_NOPULL|PIN_S
|
|||
PIN_MAP_MUX_GROUP_DEFAULT(dev, "pinctrl-db8500", group, func)
|
||||
#define DB8500_PIN(pin,conf,dev) \
|
||||
PIN_MAP_CONFIGS_PIN_DEFAULT(dev, "pinctrl-db8500", pin, conf)
|
||||
#define DB8500_PIN_IDLE(pin, conf, dev) \
|
||||
PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_IDLE, "pinctrl-db8500", \
|
||||
pin, conf)
|
||||
#define DB8500_PIN_SLEEP(pin, conf, dev) \
|
||||
PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
|
||||
pin, conf)
|
||||
|
||||
#define DB8500_PIN_SLEEP(pin,conf,dev) \
|
||||
PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
|
||||
pin, conf)
|
||||
#define DB8500_MUX_STATE(group, func, dev, state) \
|
||||
PIN_MAP_MUX_GROUP(dev, state, "pinctrl-db8500", group, func)
|
||||
#define DB8500_PIN_STATE(pin, conf, dev, state) \
|
||||
PIN_MAP_CONFIGS_PIN(dev, state, "pinctrl-db8500", pin, conf)
|
||||
|
||||
/* Pin control settings */
|
||||
static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
||||
|
@ -112,7 +133,7 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
* UART0, we do not mux in u0 here.
|
||||
* uart-0 pins gpio configuration should be kept intact to prevent
|
||||
* a glitch in tx line when the tty dev is opened. Later these pins
|
||||
* are configured to uart mop500_pins_uart0
|
||||
* are configured by uart driver
|
||||
*/
|
||||
DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
|
||||
DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
|
||||
|
@ -123,12 +144,13 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
* TODO: is this used on U8500 variants and Snowball really?
|
||||
* The setting on GPIO31 conflicts with magnetometer use on hrefv60
|
||||
*/
|
||||
DB8500_MUX_HOG("u2rxtx_c_1", "u2"),
|
||||
DB8500_MUX_HOG("u2ctsrts_c_1", "u2"),
|
||||
DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */
|
||||
DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */
|
||||
DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */
|
||||
DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */
|
||||
/* default state for UART2 */
|
||||
DB8500_MUX("u2rxtx_c_1", "u2", "uart2"),
|
||||
DB8500_PIN("GPIO29_W2", in_pu, "uart2"), /* RXD */
|
||||
DB8500_PIN("GPIO30_W3", out_hi, "uart2"), /* TXD */
|
||||
/* Sleep state for UART2 */
|
||||
DB8500_PIN_SLEEP("GPIO29_W2", in_wkup_pdis, "uart2"),
|
||||
DB8500_PIN_SLEEP("GPIO30_W3", out_wkup_pdis, "uart2"),
|
||||
/*
|
||||
* The following pin sets were known as "runtime pins" before being
|
||||
* converted to the pinctrl model. Here we model them as "default"
|
||||
|
@ -140,11 +162,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO1_AJ3", out_hi, "uart0"), /* RTS */
|
||||
DB8500_PIN("GPIO2_AH4", in_pu, "uart0"), /* RXD */
|
||||
DB8500_PIN("GPIO3_AH3", out_hi, "uart0"), /* TXD */
|
||||
/* UART0 sleep state */
|
||||
/* Sleep state for UART0 */
|
||||
DB8500_PIN_SLEEP("GPIO0_AJ5", slpm_in_wkup_pdis, "uart0"),
|
||||
DB8500_PIN_SLEEP("GPIO1_AJ3", slpm_out_hi_wkup_pdis, "uart0"),
|
||||
DB8500_PIN_SLEEP("GPIO2_AH4", slpm_in_wkup_pdis, "uart0"),
|
||||
DB8500_PIN_SLEEP("GPIO3_AH3", slpm_out_wkup_pdis, "uart0"),
|
||||
/* Mux in UART1 after initialization */
|
||||
DB8500_MUX("u1rxtx_a_1", "u1", "uart1"),
|
||||
DB8500_PIN("GPIO4_AH6", in_pu, "uart1"), /* RXD */
|
||||
DB8500_PIN("GPIO5_AG6", out_hi, "uart1"), /* TXD */
|
||||
/* Sleep state for UART1 */
|
||||
DB8500_PIN_SLEEP("GPIO4_AH6", slpm_in_wkup_pdis, "uart1"),
|
||||
DB8500_PIN_SLEEP("GPIO5_AG6", slpm_out_wkup_pdis, "uart1"),
|
||||
/* MSP1 for ALSA codec */
|
||||
DB8500_MUX("msp1txrx_a_1", "msp1", "ux500-msp-i2s.1"),
|
||||
DB8500_MUX("msp1_a_1", "msp1", "ux500-msp-i2s.1"),
|
||||
|
@ -161,7 +190,10 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_MUX("lcd_d8_d11_a_1", "lcd", "mcde-tvout"),
|
||||
DB8500_MUX("lcdaclk_b_1", "lcda", "mcde-tvout"),
|
||||
/* Mux in LCD VSI1 and pull it up for MCDE HDMI output */
|
||||
DB8500_MUX("lcdvsi1_a_1", "lcd", "av8100-hdmi"),
|
||||
DB8500_MUX("lcdvsi1_a_1", "lcd", "0-0070"),
|
||||
DB8500_PIN("GPIO69_E2", in_pu, "0-0070"),
|
||||
/* LCD VSI1 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO69_E2", slpm_in_wkup_pdis, "0-0070"),
|
||||
/* Mux in i2c0 block, default state */
|
||||
DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"),
|
||||
/* i2c0 sleep state */
|
||||
|
@ -194,6 +226,18 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */
|
||||
DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */
|
||||
DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */
|
||||
/* SDI0 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO18_AC2", slpm_out_hi_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO19_AC1", slpm_out_hi_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO20_AB4", slpm_out_hi_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO22_AA3", slpm_in_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO23_AA4", slpm_out_lo_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO24_AB2", slpm_in_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO25_Y4", slpm_in_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO26_Y2", slpm_in_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO27_AA2", slpm_in_wkup_pdis, "sdi0"),
|
||||
DB8500_PIN_SLEEP("GPIO28_AA1", slpm_in_wkup_pdis, "sdi0"),
|
||||
|
||||
/* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */
|
||||
DB8500_MUX("mc1_a_1", "mc1", "sdi1"),
|
||||
DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */
|
||||
|
@ -203,6 +247,15 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */
|
||||
DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */
|
||||
DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */
|
||||
/* SDI1 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO208_AH16", slpm_out_lo_wkup_pdis, "sdi1"), /* CLK */
|
||||
DB8500_PIN_SLEEP("GPIO209_AG15", slpm_in_wkup_pdis, "sdi1"), /* FBCLK */
|
||||
DB8500_PIN_SLEEP("GPIO210_AJ15", slpm_in_wkup_pdis, "sdi1"), /* CMD */
|
||||
DB8500_PIN_SLEEP("GPIO211_AG14", slpm_in_wkup_pdis, "sdi1"), /* DAT0 */
|
||||
DB8500_PIN_SLEEP("GPIO212_AF13", slpm_in_wkup_pdis, "sdi1"), /* DAT1 */
|
||||
DB8500_PIN_SLEEP("GPIO213_AG13", slpm_in_wkup_pdis, "sdi1"), /* DAT2 */
|
||||
DB8500_PIN_SLEEP("GPIO214_AH15", slpm_in_wkup_pdis, "sdi1"), /* DAT3 */
|
||||
|
||||
/* Mux in SDI2 (here called MC2) used for for PoP eMMC */
|
||||
DB8500_MUX("mc2_a_1", "mc2", "sdi2"),
|
||||
DB8500_PIN("GPIO128_A5", out_lo, "sdi2"), /* CLK */
|
||||
|
@ -216,6 +269,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO136_C7", in_pu, "sdi2"), /* DAT5 */
|
||||
DB8500_PIN("GPIO137_A7", in_pu, "sdi2"), /* DAT6 */
|
||||
DB8500_PIN("GPIO138_C5", in_pu, "sdi2"), /* DAT7 */
|
||||
/* SDI2 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO128_A5", out_lo_wkup_pdis, "sdi2"), /* CLK */
|
||||
DB8500_PIN_SLEEP("GPIO129_B4", in_wkup_pdis_en, "sdi2"), /* CMD */
|
||||
DB8500_PIN_SLEEP("GPIO130_C8", in_wkup_pdis_en, "sdi2"), /* FBCLK */
|
||||
DB8500_PIN_SLEEP("GPIO131_A12", in_wkup_pdis, "sdi2"), /* DAT0 */
|
||||
DB8500_PIN_SLEEP("GPIO132_C10", in_wkup_pdis, "sdi2"), /* DAT1 */
|
||||
DB8500_PIN_SLEEP("GPIO133_B10", in_wkup_pdis, "sdi2"), /* DAT2 */
|
||||
DB8500_PIN_SLEEP("GPIO134_B9", in_wkup_pdis, "sdi2"), /* DAT3 */
|
||||
DB8500_PIN_SLEEP("GPIO135_A9", in_wkup_pdis, "sdi2"), /* DAT4 */
|
||||
DB8500_PIN_SLEEP("GPIO136_C7", in_wkup_pdis, "sdi2"), /* DAT5 */
|
||||
DB8500_PIN_SLEEP("GPIO137_A7", in_wkup_pdis, "sdi2"), /* DAT6 */
|
||||
DB8500_PIN_SLEEP("GPIO138_C5", in_wkup_pdis, "sdi2"), /* DAT7 */
|
||||
|
||||
/* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */
|
||||
DB8500_MUX("mc4_a_1", "mc4", "sdi4"),
|
||||
DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */
|
||||
|
@ -229,6 +295,19 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */
|
||||
DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */
|
||||
DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */
|
||||
/*SDI4 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO197_AH24", slpm_in_wkup_pdis, "sdi4"), /* DAT3 */
|
||||
DB8500_PIN_SLEEP("GPIO198_AG25", slpm_in_wkup_pdis, "sdi4"), /* DAT2 */
|
||||
DB8500_PIN_SLEEP("GPIO199_AH23", slpm_in_wkup_pdis, "sdi4"), /* DAT1 */
|
||||
DB8500_PIN_SLEEP("GPIO200_AH26", slpm_in_wkup_pdis, "sdi4"), /* DAT0 */
|
||||
DB8500_PIN_SLEEP("GPIO201_AF24", slpm_in_wkup_pdis, "sdi4"), /* CMD */
|
||||
DB8500_PIN_SLEEP("GPIO202_AF25", slpm_in_wkup_pdis, "sdi4"), /* FBCLK */
|
||||
DB8500_PIN_SLEEP("GPIO203_AE23", slpm_out_lo_wkup_pdis, "sdi4"), /* CLK */
|
||||
DB8500_PIN_SLEEP("GPIO204_AF23", slpm_in_wkup_pdis, "sdi4"), /* DAT7 */
|
||||
DB8500_PIN_SLEEP("GPIO205_AG23", slpm_in_wkup_pdis, "sdi4"), /* DAT6 */
|
||||
DB8500_PIN_SLEEP("GPIO206_AG24", slpm_in_wkup_pdis, "sdi4"), /* DAT5 */
|
||||
DB8500_PIN_SLEEP("GPIO207_AJ23", slpm_in_wkup_pdis, "sdi4"), /* DAT4 */
|
||||
|
||||
/* Mux in USB pins, drive STP high */
|
||||
DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
|
||||
DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
|
||||
|
@ -238,10 +317,232 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
|
|||
DB8500_PIN("GPIO218_AH11", in_pd, "spi2"), /* RXD */
|
||||
DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
|
||||
DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
|
||||
/* SPI2 sleep state */
|
||||
/* SPI2 idle state */
|
||||
DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
|
||||
DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
|
||||
DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
|
||||
/* SPI2 sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */
|
||||
DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
|
||||
DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
|
||||
DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
|
||||
|
||||
/* ske default state */
|
||||
DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
|
||||
DB8500_PIN("GPIO153_B17", in_pd, "nmk-ske-keypad"), /* I7 */
|
||||
DB8500_PIN("GPIO154_C16", in_pd, "nmk-ske-keypad"), /* I6 */
|
||||
DB8500_PIN("GPIO155_C19", in_pd, "nmk-ske-keypad"), /* I5 */
|
||||
DB8500_PIN("GPIO156_C17", in_pd, "nmk-ske-keypad"), /* I4 */
|
||||
DB8500_PIN("GPIO161_D21", in_pd, "nmk-ske-keypad"), /* I3 */
|
||||
DB8500_PIN("GPIO162_D20", in_pd, "nmk-ske-keypad"), /* I2 */
|
||||
DB8500_PIN("GPIO163_C20", in_pd, "nmk-ske-keypad"), /* I1 */
|
||||
DB8500_PIN("GPIO164_B21", in_pd, "nmk-ske-keypad"), /* I0 */
|
||||
DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
|
||||
DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
|
||||
DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
|
||||
DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
|
||||
DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
|
||||
DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
|
||||
DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
|
||||
DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
|
||||
/* ske sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
|
||||
DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
|
||||
DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
|
||||
DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
|
||||
DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
|
||||
DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
|
||||
DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
|
||||
DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
|
||||
DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
|
||||
DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
|
||||
DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
|
||||
DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
|
||||
DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
|
||||
DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
|
||||
DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
|
||||
DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
|
||||
|
||||
/* STM APE pins states */
|
||||
DB8500_MUX_STATE("stmape_c_1", "stmape",
|
||||
"stm", "ape_mipi34"),
|
||||
DB8500_PIN_STATE("GPIO70_G5", in_nopull,
|
||||
"stm", "ape_mipi34"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", in_nopull,
|
||||
"stm", "ape_mipi34"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", in_nopull,
|
||||
"stm", "ape_mipi34"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", in_nopull,
|
||||
"stm", "ape_mipi34"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", in_nopull,
|
||||
"stm", "ape_mipi34"), /* dat0 */
|
||||
|
||||
DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
|
||||
"stm", "ape_mipi34_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
|
||||
"stm", "ape_mipi34_sleep"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
|
||||
"stm", "ape_mipi34_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
|
||||
"stm", "ape_mipi34_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
|
||||
"stm", "ape_mipi34_sleep"), /* dat0 */
|
||||
|
||||
DB8500_MUX_STATE("stmape_oc1_1", "stmape",
|
||||
"stm", "ape_microsd"),
|
||||
DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
|
||||
"stm", "ape_microsd"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
|
||||
"stm", "ape_microsd"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
|
||||
"stm", "ape_microsd"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
|
||||
"stm", "ape_microsd"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
|
||||
"stm", "ape_microsd"), /* dat3 */
|
||||
|
||||
DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
|
||||
"stm", "ape_microsd_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
|
||||
"stm", "ape_microsd_sleep"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
|
||||
"stm", "ape_microsd_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
|
||||
"stm", "ape_microsd_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
|
||||
"stm", "ape_microsd_sleep"), /* dat3 */
|
||||
|
||||
/* STM Modem pins states */
|
||||
DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
|
||||
"stm", "mod_mipi34"),
|
||||
DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
|
||||
"stm", "mod_mipi34"),
|
||||
DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
|
||||
"stm", "mod_mipi34"),
|
||||
DB8500_PIN_STATE("GPIO70_G5", in_nopull,
|
||||
"stm", "mod_mipi34"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", in_nopull,
|
||||
"stm", "mod_mipi34"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", in_nopull,
|
||||
"stm", "mod_mipi34"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", in_nopull,
|
||||
"stm", "mod_mipi34"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", in_nopull,
|
||||
"stm", "mod_mipi34"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", in_pu,
|
||||
"stm", "mod_mipi34"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", out_lo,
|
||||
"stm", "mod_mipi34"), /* uartmod tx */
|
||||
|
||||
DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
|
||||
"stm", "mod_mipi34_sleep"), /* uartmod tx */
|
||||
|
||||
DB8500_MUX_STATE("stmmod_b_1", "stmmod",
|
||||
"stm", "mod_microsd"),
|
||||
DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
|
||||
"stm", "mod_microsd"),
|
||||
DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
|
||||
"stm", "mod_microsd"),
|
||||
DB8500_PIN_STATE("GPIO23_AA4", in_nopull,
|
||||
"stm", "mod_microsd"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO25_Y4", in_nopull,
|
||||
"stm", "mod_microsd"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO26_Y2", in_nopull,
|
||||
"stm", "mod_microsd"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO27_AA2", in_nopull,
|
||||
"stm", "mod_microsd"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO28_AA1", in_nopull,
|
||||
"stm", "mod_microsd"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", in_pu,
|
||||
"stm", "mod_microsd"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", out_lo,
|
||||
"stm", "mod_microsd"), /* uartmod tx */
|
||||
|
||||
DB8500_PIN_STATE("GPIO23_AA4", slpm_out_lo_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO25_Y4", slpm_in_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO26_Y2", slpm_in_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO27_AA2", slpm_in_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO28_AA1", slpm_in_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
|
||||
"stm", "mod_microsd_sleep"), /* uartmod tx */
|
||||
|
||||
/* STM dual Modem/APE pins state */
|
||||
DB8500_MUX_STATE("stmmod_oc3_2", "stmmod",
|
||||
"stm", "mod_mipi34_ape_mipi60"),
|
||||
DB8500_MUX_STATE("stmape_c_2", "stmape",
|
||||
"stm", "mod_mipi34_ape_mipi60"),
|
||||
DB8500_MUX_STATE("uartmodrx_oc3_1", "uartmod",
|
||||
"stm", "mod_mipi34_ape_mipi60"),
|
||||
DB8500_MUX_STATE("uartmodtx_oc3_1", "uartmod",
|
||||
"stm", "mod_mipi34_ape_mipi60"),
|
||||
DB8500_PIN_STATE("GPIO70_G5", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", in_pu,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", out_lo,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* uartmod tx */
|
||||
DB8500_PIN_STATE("GPIO155_C19", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO156_C17", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO157_A18", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO158_C18", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO159_B19", in_nopull,
|
||||
"stm", "mod_mipi34_ape_mipi60"), /* dat0 */
|
||||
|
||||
DB8500_PIN_STATE("GPIO70_G5", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO71_G4", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO72_H4", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO73_H3", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO74_J3", slpm_out_lo_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
|
||||
DB8500_PIN_STATE("GPIO75_H2", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod rx */
|
||||
DB8500_PIN_STATE("GPIO76_J2", slpm_out_lo_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* uartmod tx */
|
||||
DB8500_PIN_STATE("GPIO155_C19", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* clk */
|
||||
DB8500_PIN_STATE("GPIO156_C17", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat3 */
|
||||
DB8500_PIN_STATE("GPIO157_A18", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat2 */
|
||||
DB8500_PIN_STATE("GPIO158_C18", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat1 */
|
||||
DB8500_PIN_STATE("GPIO159_B19", slpm_in_wkup_pdis,
|
||||
"stm", "mod_mipi34_ape_mipi60_sleep"), /* dat0 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -267,32 +568,48 @@ static struct pinctrl_map __initdata mop500_pinmap[] = {
|
|||
DB8500_PIN_HOG("GPIO217_AH12", gpio_in_pu),
|
||||
/* Mux in UART1 and set the pull-ups */
|
||||
DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
|
||||
DB8500_MUX_HOG("u1ctsrts_a_1", "u1"),
|
||||
DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
|
||||
DB8500_PIN_HOG("GPIO5_AG6", out_hi), /* TXD */
|
||||
DB8500_PIN_HOG("GPIO6_AF6", in_pu), /* CTS */
|
||||
DB8500_PIN_HOG("GPIO7_AG5", out_hi), /* RTS */
|
||||
/*
|
||||
* Runtime stuff: make it possible to mux in the SKE keypad
|
||||
* and bias the pins
|
||||
*/
|
||||
DB8500_MUX("kp_a_2", "kp", "ske"),
|
||||
DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
|
||||
DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
|
||||
DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
|
||||
DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
|
||||
DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
|
||||
DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
|
||||
DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
|
||||
DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
|
||||
DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
|
||||
DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
|
||||
DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
|
||||
DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
|
||||
DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
|
||||
DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
|
||||
DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
|
||||
DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
|
||||
/* ske default state */
|
||||
DB8500_MUX("kp_a_2", "kp", "nmk-ske-keypad"),
|
||||
DB8500_PIN("GPIO153_B17", in_pu, "nmk-ske-keypad"), /* I7 */
|
||||
DB8500_PIN("GPIO154_C16", in_pu, "nmk-ske-keypad"), /* I6 */
|
||||
DB8500_PIN("GPIO155_C19", in_pu, "nmk-ske-keypad"), /* I5 */
|
||||
DB8500_PIN("GPIO156_C17", in_pu, "nmk-ske-keypad"), /* I4 */
|
||||
DB8500_PIN("GPIO161_D21", in_pu, "nmk-ske-keypad"), /* I3 */
|
||||
DB8500_PIN("GPIO162_D20", in_pu, "nmk-ske-keypad"), /* I2 */
|
||||
DB8500_PIN("GPIO163_C20", in_pu, "nmk-ske-keypad"), /* I1 */
|
||||
DB8500_PIN("GPIO164_B21", in_pu, "nmk-ske-keypad"), /* I0 */
|
||||
DB8500_PIN("GPIO157_A18", out_lo, "nmk-ske-keypad"), /* O7 */
|
||||
DB8500_PIN("GPIO158_C18", out_lo, "nmk-ske-keypad"), /* O6 */
|
||||
DB8500_PIN("GPIO159_B19", out_lo, "nmk-ske-keypad"), /* O5 */
|
||||
DB8500_PIN("GPIO160_B20", out_lo, "nmk-ske-keypad"), /* O4 */
|
||||
DB8500_PIN("GPIO165_C21", out_lo, "nmk-ske-keypad"), /* O3 */
|
||||
DB8500_PIN("GPIO166_A22", out_lo, "nmk-ske-keypad"), /* O2 */
|
||||
DB8500_PIN("GPIO167_B24", out_lo, "nmk-ske-keypad"), /* O1 */
|
||||
DB8500_PIN("GPIO168_C22", out_lo, "nmk-ske-keypad"), /* O0 */
|
||||
/* ske sleep state */
|
||||
DB8500_PIN_SLEEP("GPIO153_B17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I7 */
|
||||
DB8500_PIN_SLEEP("GPIO154_C16", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I6 */
|
||||
DB8500_PIN_SLEEP("GPIO155_C19", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I5 */
|
||||
DB8500_PIN_SLEEP("GPIO156_C17", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I4 */
|
||||
DB8500_PIN_SLEEP("GPIO161_D21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I3 */
|
||||
DB8500_PIN_SLEEP("GPIO162_D20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I2 */
|
||||
DB8500_PIN_SLEEP("GPIO163_C20", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I1 */
|
||||
DB8500_PIN_SLEEP("GPIO164_B21", slpm_in_pu_wkup_pdis_en, "nmk-ske-keypad"), /* I0 */
|
||||
DB8500_PIN_SLEEP("GPIO157_A18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O7 */
|
||||
DB8500_PIN_SLEEP("GPIO158_C18", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O6 */
|
||||
DB8500_PIN_SLEEP("GPIO159_B19", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O5 */
|
||||
DB8500_PIN_SLEEP("GPIO160_B20", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O4 */
|
||||
DB8500_PIN_SLEEP("GPIO165_C21", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O3 */
|
||||
DB8500_PIN_SLEEP("GPIO166_A22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O2 */
|
||||
DB8500_PIN_SLEEP("GPIO167_B24", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O1 */
|
||||
DB8500_PIN_SLEEP("GPIO168_C22", slpm_out_lo_pdis, "nmk-ske-keypad"), /* O0 */
|
||||
|
||||
/* Mux in and drive the SDI0 DAT31DIR line high at runtime */
|
||||
DB8500_MUX("mc0dat31dir_a_1", "mc0", "sdi0"),
|
||||
DB8500_PIN("GPIO21_AB3", out_hi, "sdi0"),
|
||||
|
@ -395,28 +712,6 @@ static struct pinctrl_map __initdata hrefv60_pinmap[] = {
|
|||
DB8500_PIN("GPIO217_AH12", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
|
||||
DB8500_PIN("GPIO145_C13", gpio_in_pd_slpm_gpio_nopull, "gpio-keys.0"),
|
||||
DB8500_PIN("GPIO139_C9", gpio_in_pu_slpm_gpio_nopull, "gpio-keys.0"),
|
||||
/*
|
||||
* Make it possible to mux in the SKE keypad and bias the pins
|
||||
* FIXME: what's the point with this on HREFv60? KP/SKE is already
|
||||
* muxed in at another place! Enabling this will bork.
|
||||
*/
|
||||
DB8500_MUX("kp_a_2", "kp", "ske"),
|
||||
DB8500_PIN("GPIO153_B17", in_pd_slpm_in_pu, "ske"), /* I7 */
|
||||
DB8500_PIN("GPIO154_C16", in_pd_slpm_in_pu, "ske"), /* I6 */
|
||||
DB8500_PIN("GPIO155_C19", in_pd_slpm_in_pu, "ske"), /* I5 */
|
||||
DB8500_PIN("GPIO156_C17", in_pd_slpm_in_pu, "ske"), /* I4 */
|
||||
DB8500_PIN("GPIO161_D21", in_pd_slpm_in_pu, "ske"), /* I3 */
|
||||
DB8500_PIN("GPIO162_D20", in_pd_slpm_in_pu, "ske"), /* I2 */
|
||||
DB8500_PIN("GPIO163_C20", in_pd_slpm_in_pu, "ske"), /* I1 */
|
||||
DB8500_PIN("GPIO164_B21", in_pd_slpm_in_pu, "ske"), /* I0 */
|
||||
DB8500_PIN("GPIO157_A18", in_pu_slpm_out_lo, "ske"), /* O7 */
|
||||
DB8500_PIN("GPIO158_C18", in_pu_slpm_out_lo, "ske"), /* O6 */
|
||||
DB8500_PIN("GPIO159_B19", in_pu_slpm_out_lo, "ske"), /* O5 */
|
||||
DB8500_PIN("GPIO160_B20", in_pu_slpm_out_lo, "ske"), /* O4 */
|
||||
DB8500_PIN("GPIO165_C21", in_pu_slpm_out_lo, "ske"), /* O3 */
|
||||
DB8500_PIN("GPIO166_A22", in_pu_slpm_out_lo, "ske"), /* O2 */
|
||||
DB8500_PIN("GPIO167_B24", in_pu_slpm_out_lo, "ske"), /* O1 */
|
||||
DB8500_PIN("GPIO168_C22", in_pu_slpm_out_lo, "ske"), /* O0 */
|
||||
};
|
||||
|
||||
static struct pinctrl_map __initdata u9500_pinmap[] = {
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Limited
|
||||
*/
|
||||
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
static void vexpress_reset_do(struct device *dev, const char *what)
|
||||
{
|
||||
int err = -ENOENT;
|
||||
struct vexpress_config_func *func =
|
||||
vexpress_config_func_get_by_dev(dev);
|
||||
|
||||
if (func) {
|
||||
unsigned long timeout;
|
||||
|
||||
err = vexpress_config_write(func, 0, 0);
|
||||
|
||||
timeout = jiffies + HZ;
|
||||
while (time_before(jiffies, timeout))
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
dev_emerg(dev, "Unable to %s (%d)\n", what, err);
|
||||
}
|
||||
|
||||
static struct device *vexpress_power_off_device;
|
||||
|
||||
void vexpress_power_off(void)
|
||||
{
|
||||
vexpress_reset_do(vexpress_power_off_device, "power off");
|
||||
}
|
||||
|
||||
static struct device *vexpress_restart_device;
|
||||
|
||||
void vexpress_restart(char str, const char *cmd)
|
||||
{
|
||||
vexpress_reset_do(vexpress_restart_device, "restart");
|
||||
}
|
||||
|
||||
static ssize_t vexpress_reset_active_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", vexpress_restart_device == dev);
|
||||
}
|
||||
|
||||
static ssize_t vexpress_reset_active_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
long value;
|
||||
int err = kstrtol(buf, 0, &value);
|
||||
|
||||
if (!err && value)
|
||||
vexpress_restart_device = dev;
|
||||
|
||||
return err ? err : count;
|
||||
}
|
||||
|
||||
DEVICE_ATTR(active, S_IRUGO | S_IWUSR, vexpress_reset_active_show,
|
||||
vexpress_reset_active_store);
|
||||
|
||||
|
||||
enum vexpress_reset_func { FUNC_RESET, FUNC_SHUTDOWN, FUNC_REBOOT };
|
||||
|
||||
static struct of_device_id vexpress_reset_of_match[] = {
|
||||
{
|
||||
.compatible = "arm,vexpress-reset",
|
||||
.data = (void *)FUNC_RESET,
|
||||
}, {
|
||||
.compatible = "arm,vexpress-shutdown",
|
||||
.data = (void *)FUNC_SHUTDOWN
|
||||
}, {
|
||||
.compatible = "arm,vexpress-reboot",
|
||||
.data = (void *)FUNC_REBOOT
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static int vexpress_reset_probe(struct platform_device *pdev)
|
||||
{
|
||||
enum vexpress_reset_func func;
|
||||
const struct of_device_id *match =
|
||||
of_match_device(vexpress_reset_of_match, &pdev->dev);
|
||||
|
||||
if (match)
|
||||
func = (enum vexpress_reset_func)match->data;
|
||||
else
|
||||
func = pdev->id_entry->driver_data;
|
||||
|
||||
switch (func) {
|
||||
case FUNC_SHUTDOWN:
|
||||
vexpress_power_off_device = &pdev->dev;
|
||||
break;
|
||||
case FUNC_RESET:
|
||||
if (!vexpress_restart_device)
|
||||
vexpress_restart_device = &pdev->dev;
|
||||
device_create_file(&pdev->dev, &dev_attr_active);
|
||||
break;
|
||||
case FUNC_REBOOT:
|
||||
vexpress_restart_device = &pdev->dev;
|
||||
device_create_file(&pdev->dev, &dev_attr_active);
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id vexpress_reset_id_table[] = {
|
||||
{ .name = "vexpress-reset", .driver_data = FUNC_RESET, },
|
||||
{ .name = "vexpress-shutdown", .driver_data = FUNC_SHUTDOWN, },
|
||||
{ .name = "vexpress-reboot", .driver_data = FUNC_REBOOT, },
|
||||
{}
|
||||
};
|
||||
|
||||
static struct platform_driver vexpress_reset_driver = {
|
||||
.probe = vexpress_reset_probe,
|
||||
.driver = {
|
||||
.name = "vexpress-reset",
|
||||
.of_match_table = vexpress_reset_of_match,
|
||||
},
|
||||
.id_table = vexpress_reset_id_table,
|
||||
};
|
||||
|
||||
static int __init vexpress_reset_init(void)
|
||||
{
|
||||
return platform_driver_register(&vexpress_reset_driver);
|
||||
}
|
||||
device_initcall(vexpress_reset_init);
|
|
@ -48,6 +48,7 @@ struct samsung_gpio_cfg;
|
|||
* @config: special function and pull-resistor control information.
|
||||
* @lock: Lock for exclusive access to this gpio bank.
|
||||
* @pm_save: Save information for suspend/resume support.
|
||||
* @bitmap_gpio_int: Bitmap for representing GPIO interrupt or not.
|
||||
*
|
||||
* This wrapper provides the necessary information for the Samsung
|
||||
* specific gpios being registered with gpiolib.
|
||||
|
@ -71,6 +72,7 @@ struct samsung_gpio_chip {
|
|||
#ifdef CONFIG_PM
|
||||
u32 pm_save[4];
|
||||
#endif
|
||||
u32 bitmap_gpio_int;
|
||||
};
|
||||
|
||||
static inline struct samsung_gpio_chip *to_samsung_gpio(struct gpio_chip *gpc)
|
||||
|
|
|
@ -185,7 +185,7 @@ int __init s5p_register_gpio_interrupt(int pin)
|
|||
|
||||
/* check if the group has been already registered */
|
||||
if (my_chip->irq_base)
|
||||
return my_chip->irq_base + offset;
|
||||
goto success;
|
||||
|
||||
/* register gpio group */
|
||||
ret = s5p_gpioint_add(my_chip);
|
||||
|
@ -193,9 +193,13 @@ int __init s5p_register_gpio_interrupt(int pin)
|
|||
my_chip->chip.to_irq = samsung_gpiolib_to_irq;
|
||||
printk(KERN_INFO "Registered interrupt support for gpio group %d.\n",
|
||||
group);
|
||||
return my_chip->irq_base + offset;
|
||||
goto success;
|
||||
}
|
||||
return ret;
|
||||
success:
|
||||
my_chip->bitmap_gpio_int |= BIT(offset);
|
||||
|
||||
return my_chip->irq_base + offset;
|
||||
}
|
||||
|
||||
int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
|
||||
|
|
|
@ -42,12 +42,6 @@
|
|||
#include <plat/gpio-fns.h>
|
||||
#include <plat/pm.h>
|
||||
|
||||
#ifndef DEBUG_GPIO
|
||||
#define gpio_dbg(x...) do { } while (0)
|
||||
#else
|
||||
#define gpio_dbg(x...) printk(KERN_DEBUG x)
|
||||
#endif
|
||||
|
||||
int samsung_gpio_setpull_updown(struct samsung_gpio_chip *chip,
|
||||
unsigned int off, samsung_gpio_pull_t pull)
|
||||
{
|
||||
|
@ -596,10 +590,13 @@ static int samsung_gpiolib_4bit_input(struct gpio_chip *chip,
|
|||
unsigned long con;
|
||||
|
||||
con = __raw_readl(base + GPIOCON_OFF);
|
||||
if (ourchip->bitmap_gpio_int & BIT(offset))
|
||||
con |= 0xf << con_4bit_shift(offset);
|
||||
else
|
||||
con &= ~(0xf << con_4bit_shift(offset));
|
||||
__raw_writel(con, base + GPIOCON_OFF);
|
||||
|
||||
gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con);
|
||||
pr_debug("%s: %p: CON now %08lx\n", __func__, base, con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -627,7 +624,7 @@ static int samsung_gpiolib_4bit_output(struct gpio_chip *chip,
|
|||
__raw_writel(con, base + GPIOCON_OFF);
|
||||
__raw_writel(dat, base + GPIODAT_OFF);
|
||||
|
||||
gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
|
||||
pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -671,7 +668,7 @@ static int samsung_gpiolib_4bit2_input(struct gpio_chip *chip,
|
|||
con &= ~(0xf << con_4bit_shift(offset));
|
||||
__raw_writel(con, regcon);
|
||||
|
||||
gpio_dbg("%s: %p: CON %08lx\n", __func__, base, con);
|
||||
pr_debug("%s: %p: CON %08lx\n", __func__, base, con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -706,7 +703,7 @@ static int samsung_gpiolib_4bit2_output(struct gpio_chip *chip,
|
|||
__raw_writel(con, regcon);
|
||||
__raw_writel(dat, base + GPIODAT_OFF);
|
||||
|
||||
gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
|
||||
pr_debug("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -926,10 +923,10 @@ static void __init samsung_gpiolib_add(struct samsung_gpio_chip *chip)
|
|||
#ifdef CONFIG_PM
|
||||
if (chip->pm != NULL) {
|
||||
if (!chip->pm->save || !chip->pm->resume)
|
||||
printk(KERN_ERR "gpio: %s has missing PM functions\n",
|
||||
pr_err("gpio: %s has missing PM functions\n",
|
||||
gc->label);
|
||||
} else
|
||||
printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
|
||||
pr_err("gpio: %s has no PM function\n", gc->label);
|
||||
#endif
|
||||
|
||||
/* gpiochip_add() prints own failure message on error. */
|
||||
|
@ -1081,6 +1078,8 @@ static void __init samsung_gpiolib_add_4bit_chips(struct samsung_gpio_chip *chip
|
|||
if ((base != NULL) && (chip->base == NULL))
|
||||
chip->base = base + ((i) * 0x20);
|
||||
|
||||
chip->bitmap_gpio_int = 0;
|
||||
|
||||
samsung_gpiolib_add(chip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1208,6 +1208,14 @@ config SENSORS_TWL4030_MADC
|
|||
This driver can also be built as a module. If so it will be called
|
||||
twl4030-madc-hwmon.
|
||||
|
||||
config SENSORS_VEXPRESS
|
||||
tristate "Versatile Express"
|
||||
depends on VEXPRESS_CONFIG
|
||||
help
|
||||
This driver provides support for hardware sensors available on
|
||||
the ARM Ltd's Versatile Express platform. It can provide wide
|
||||
range of information like temperature, power, energy.
|
||||
|
||||
config SENSORS_VIA_CPUTEMP
|
||||
tristate "VIA CPU temperature sensor"
|
||||
depends on X86
|
||||
|
|
|
@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
|
|||
obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
|
||||
obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
|
||||
obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
|
||||
obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o
|
||||
obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
|
||||
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
|
||||
obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Limited
|
||||
*/
|
||||
|
||||
#define DRVNAME "vexpress-hwmon"
|
||||
#define pr_fmt(fmt) DRVNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
struct vexpress_hwmon_data {
|
||||
struct device *hwmon_dev;
|
||||
struct vexpress_config_func *func;
|
||||
};
|
||||
|
||||
static ssize_t vexpress_hwmon_name_show(struct device *dev,
|
||||
struct device_attribute *dev_attr, char *buffer)
|
||||
{
|
||||
const char *compatible = of_get_property(dev->of_node, "compatible",
|
||||
NULL);
|
||||
|
||||
return sprintf(buffer, "%s\n", compatible);
|
||||
}
|
||||
|
||||
static ssize_t vexpress_hwmon_label_show(struct device *dev,
|
||||
struct device_attribute *dev_attr, char *buffer)
|
||||
{
|
||||
const char *label = of_get_property(dev->of_node, "label", NULL);
|
||||
|
||||
if (!label)
|
||||
return -ENOENT;
|
||||
|
||||
return snprintf(buffer, PAGE_SIZE, "%s\n", label);
|
||||
}
|
||||
|
||||
static ssize_t vexpress_hwmon_u32_show(struct device *dev,
|
||||
struct device_attribute *dev_attr, char *buffer)
|
||||
{
|
||||
struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
|
||||
int err;
|
||||
u32 value;
|
||||
|
||||
err = vexpress_config_read(data->func, 0, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return snprintf(buffer, PAGE_SIZE, "%u\n", value /
|
||||
to_sensor_dev_attr(dev_attr)->index);
|
||||
}
|
||||
|
||||
static ssize_t vexpress_hwmon_u64_show(struct device *dev,
|
||||
struct device_attribute *dev_attr, char *buffer)
|
||||
{
|
||||
struct vexpress_hwmon_data *data = dev_get_drvdata(dev);
|
||||
int err;
|
||||
u32 value_hi, value_lo;
|
||||
|
||||
err = vexpress_config_read(data->func, 0, &value_lo);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = vexpress_config_read(data->func, 1, &value_hi);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return snprintf(buffer, PAGE_SIZE, "%llu\n",
|
||||
div_u64(((u64)value_hi << 32) | value_lo,
|
||||
to_sensor_dev_attr(dev_attr)->index));
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, vexpress_hwmon_name_show, NULL);
|
||||
|
||||
#define VEXPRESS_HWMON_ATTRS(_name, _label_attr, _input_attr) \
|
||||
struct attribute *vexpress_hwmon_attrs_##_name[] = { \
|
||||
&dev_attr_name.attr, \
|
||||
&dev_attr_##_label_attr.attr, \
|
||||
&sensor_dev_attr_##_input_attr.dev_attr.attr, \
|
||||
NULL \
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_REGULATOR_VEXPRESS)
|
||||
static DEVICE_ATTR(in1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
|
||||
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, vexpress_hwmon_u32_show,
|
||||
NULL, 1000);
|
||||
static VEXPRESS_HWMON_ATTRS(volt, in1_label, in1_input);
|
||||
static struct attribute_group vexpress_hwmon_group_volt = {
|
||||
.attrs = vexpress_hwmon_attrs_volt,
|
||||
};
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR(curr1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
|
||||
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, vexpress_hwmon_u32_show,
|
||||
NULL, 1000);
|
||||
static VEXPRESS_HWMON_ATTRS(amp, curr1_label, curr1_input);
|
||||
static struct attribute_group vexpress_hwmon_group_amp = {
|
||||
.attrs = vexpress_hwmon_attrs_amp,
|
||||
};
|
||||
|
||||
static DEVICE_ATTR(temp1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, vexpress_hwmon_u32_show,
|
||||
NULL, 1000);
|
||||
static VEXPRESS_HWMON_ATTRS(temp, temp1_label, temp1_input);
|
||||
static struct attribute_group vexpress_hwmon_group_temp = {
|
||||
.attrs = vexpress_hwmon_attrs_temp,
|
||||
};
|
||||
|
||||
static DEVICE_ATTR(power1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
|
||||
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, vexpress_hwmon_u32_show,
|
||||
NULL, 1);
|
||||
static VEXPRESS_HWMON_ATTRS(power, power1_label, power1_input);
|
||||
static struct attribute_group vexpress_hwmon_group_power = {
|
||||
.attrs = vexpress_hwmon_attrs_power,
|
||||
};
|
||||
|
||||
static DEVICE_ATTR(energy1_label, S_IRUGO, vexpress_hwmon_label_show, NULL);
|
||||
static SENSOR_DEVICE_ATTR(energy1_input, S_IRUGO, vexpress_hwmon_u64_show,
|
||||
NULL, 1);
|
||||
static VEXPRESS_HWMON_ATTRS(energy, energy1_label, energy1_input);
|
||||
static struct attribute_group vexpress_hwmon_group_energy = {
|
||||
.attrs = vexpress_hwmon_attrs_energy,
|
||||
};
|
||||
|
||||
static struct of_device_id vexpress_hwmon_of_match[] = {
|
||||
#if !defined(CONFIG_REGULATOR_VEXPRESS)
|
||||
{
|
||||
.compatible = "arm,vexpress-volt",
|
||||
.data = &vexpress_hwmon_group_volt,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.compatible = "arm,vexpress-amp",
|
||||
.data = &vexpress_hwmon_group_amp,
|
||||
}, {
|
||||
.compatible = "arm,vexpress-temp",
|
||||
.data = &vexpress_hwmon_group_temp,
|
||||
}, {
|
||||
.compatible = "arm,vexpress-power",
|
||||
.data = &vexpress_hwmon_group_power,
|
||||
}, {
|
||||
.compatible = "arm,vexpress-energy",
|
||||
.data = &vexpress_hwmon_group_energy,
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, vexpress_hwmon_of_match);
|
||||
|
||||
static int vexpress_hwmon_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
const struct of_device_id *match;
|
||||
struct vexpress_hwmon_data *data;
|
||||
|
||||
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
data->func = vexpress_config_func_get_by_dev(&pdev->dev);
|
||||
if (!data->func)
|
||||
return -ENODEV;
|
||||
|
||||
err = sysfs_create_group(&pdev->dev.kobj, match->data);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&pdev->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
sysfs_remove_group(&pdev->dev.kobj, match->data);
|
||||
vexpress_config_func_put(data->func);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit vexpress_hwmon_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vexpress_hwmon_data *data = platform_get_drvdata(pdev);
|
||||
const struct of_device_id *match;
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
|
||||
match = of_match_device(vexpress_hwmon_of_match, &pdev->dev);
|
||||
sysfs_remove_group(&pdev->dev.kobj, match->data);
|
||||
|
||||
vexpress_config_func_put(data->func);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver vexpress_hwmon_driver = {
|
||||
.probe = vexpress_hwmon_probe,
|
||||
.remove = __devexit_p(vexpress_hwmon_remove),
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = vexpress_hwmon_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(vexpress_hwmon_driver);
|
||||
|
||||
MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
|
||||
MODULE_DESCRIPTION("Versatile Express hwmon sensors driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:vexpress-hwmon");
|
Loading…
Reference in New Issue