162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * linux/arch/arm/mach-omap1/devices.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * OMAP1 platform device setup/initialization
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/spi/spi.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/platform_data/omap-wd-timer.h>
1662306a36Sopenharmony_ci#include <linux/soc/ti/omap1-io.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <asm/mach/map.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include "tc.h"
2162306a36Sopenharmony_ci#include "mux.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include "hardware.h"
2462306a36Sopenharmony_ci#include "common.h"
2562306a36Sopenharmony_ci#include "clock.h"
2662306a36Sopenharmony_ci#include "mmc.h"
2762306a36Sopenharmony_ci#include "sram.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_RTC_DRV_OMAP)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define	OMAP_RTC_BASE		0xfffb4800
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic struct resource rtc_resources[] = {
3462306a36Sopenharmony_ci	{
3562306a36Sopenharmony_ci		.start		= OMAP_RTC_BASE,
3662306a36Sopenharmony_ci		.end		= OMAP_RTC_BASE + 0x5f,
3762306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
3862306a36Sopenharmony_ci	},
3962306a36Sopenharmony_ci	{
4062306a36Sopenharmony_ci		.start		= INT_RTC_TIMER,
4162306a36Sopenharmony_ci		.flags		= IORESOURCE_IRQ,
4262306a36Sopenharmony_ci	},
4362306a36Sopenharmony_ci	{
4462306a36Sopenharmony_ci		.start		= INT_RTC_ALARM,
4562306a36Sopenharmony_ci		.flags		= IORESOURCE_IRQ,
4662306a36Sopenharmony_ci	},
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic struct platform_device omap_rtc_device = {
5062306a36Sopenharmony_ci	.name           = "omap_rtc",
5162306a36Sopenharmony_ci	.id             = -1,
5262306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(rtc_resources),
5362306a36Sopenharmony_ci	.resource	= rtc_resources,
5462306a36Sopenharmony_ci};
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic void omap_init_rtc(void)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	(void) platform_device_register(&omap_rtc_device);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci#else
6162306a36Sopenharmony_cistatic inline void omap_init_rtc(void) {}
6262306a36Sopenharmony_ci#endif
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_MMC_OMAP)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic inline void omap1_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
6962306a36Sopenharmony_ci			int controller_nr)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	if (controller_nr == 0) {
7262306a36Sopenharmony_ci		omap_cfg_reg(MMC_CMD);
7362306a36Sopenharmony_ci		omap_cfg_reg(MMC_CLK);
7462306a36Sopenharmony_ci		omap_cfg_reg(MMC_DAT0);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci		if (cpu_is_omap1710()) {
7762306a36Sopenharmony_ci			omap_cfg_reg(M15_1710_MMC_CLKI);
7862306a36Sopenharmony_ci			omap_cfg_reg(P19_1710_MMC_CMDDIR);
7962306a36Sopenharmony_ci			omap_cfg_reg(P20_1710_MMC_DATDIR0);
8062306a36Sopenharmony_ci		}
8162306a36Sopenharmony_ci		if (mmc_controller->slots[0].wires == 4) {
8262306a36Sopenharmony_ci			omap_cfg_reg(MMC_DAT1);
8362306a36Sopenharmony_ci			/* NOTE: DAT2 can be on W10 (here) or M15 */
8462306a36Sopenharmony_ci			if (!mmc_controller->slots[0].nomux)
8562306a36Sopenharmony_ci				omap_cfg_reg(MMC_DAT2);
8662306a36Sopenharmony_ci			omap_cfg_reg(MMC_DAT3);
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci	}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* Block 2 is on newer chips, and has many pinout options */
9162306a36Sopenharmony_ci	if (cpu_is_omap16xx() && controller_nr == 1) {
9262306a36Sopenharmony_ci		if (!mmc_controller->slots[1].nomux) {
9362306a36Sopenharmony_ci			omap_cfg_reg(Y8_1610_MMC2_CMD);
9462306a36Sopenharmony_ci			omap_cfg_reg(Y10_1610_MMC2_CLK);
9562306a36Sopenharmony_ci			omap_cfg_reg(R18_1610_MMC2_CLKIN);
9662306a36Sopenharmony_ci			omap_cfg_reg(W8_1610_MMC2_DAT0);
9762306a36Sopenharmony_ci			if (mmc_controller->slots[1].wires == 4) {
9862306a36Sopenharmony_ci				omap_cfg_reg(V8_1610_MMC2_DAT1);
9962306a36Sopenharmony_ci				omap_cfg_reg(W15_1610_MMC2_DAT2);
10062306a36Sopenharmony_ci				omap_cfg_reg(R10_1610_MMC2_DAT3);
10162306a36Sopenharmony_ci			}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci			/* These are needed for the level shifter */
10462306a36Sopenharmony_ci			omap_cfg_reg(V9_1610_MMC2_CMDDIR);
10562306a36Sopenharmony_ci			omap_cfg_reg(V5_1610_MMC2_DATDIR0);
10662306a36Sopenharmony_ci			omap_cfg_reg(W19_1610_MMC2_DATDIR1);
10762306a36Sopenharmony_ci		}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci		/* Feedback clock must be set on OMAP-1710 MMC2 */
11062306a36Sopenharmony_ci		if (cpu_is_omap1710())
11162306a36Sopenharmony_ci			omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24),
11262306a36Sopenharmony_ci					MOD_CONF_CTRL_1);
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci#define OMAP_MMC_NR_RES		4
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/*
11962306a36Sopenharmony_ci * Register MMC devices.
12062306a36Sopenharmony_ci */
12162306a36Sopenharmony_cistatic int __init omap_mmc_add(const char *name, int id, unsigned long base,
12262306a36Sopenharmony_ci				unsigned long size, unsigned int irq,
12362306a36Sopenharmony_ci				unsigned rx_req, unsigned tx_req,
12462306a36Sopenharmony_ci				struct omap_mmc_platform_data *data)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	struct platform_device *pdev;
12762306a36Sopenharmony_ci	struct resource res[OMAP_MMC_NR_RES];
12862306a36Sopenharmony_ci	int ret;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	pdev = platform_device_alloc(name, id);
13162306a36Sopenharmony_ci	if (!pdev)
13262306a36Sopenharmony_ci		return -ENOMEM;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	memset(res, 0, OMAP_MMC_NR_RES * sizeof(struct resource));
13562306a36Sopenharmony_ci	res[0].start = base;
13662306a36Sopenharmony_ci	res[0].end = base + size - 1;
13762306a36Sopenharmony_ci	res[0].flags = IORESOURCE_MEM;
13862306a36Sopenharmony_ci	res[1].start = res[1].end = irq;
13962306a36Sopenharmony_ci	res[1].flags = IORESOURCE_IRQ;
14062306a36Sopenharmony_ci	res[2].start = rx_req;
14162306a36Sopenharmony_ci	res[2].name = "rx";
14262306a36Sopenharmony_ci	res[2].flags = IORESOURCE_DMA;
14362306a36Sopenharmony_ci	res[3].start = tx_req;
14462306a36Sopenharmony_ci	res[3].name = "tx";
14562306a36Sopenharmony_ci	res[3].flags = IORESOURCE_DMA;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	if (cpu_is_omap15xx())
14862306a36Sopenharmony_ci		data->slots[0].features = MMC_OMAP15XX;
14962306a36Sopenharmony_ci	if (cpu_is_omap16xx())
15062306a36Sopenharmony_ci		data->slots[0].features = MMC_OMAP16XX;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
15362306a36Sopenharmony_ci	if (ret == 0)
15462306a36Sopenharmony_ci		ret = platform_device_add_data(pdev, data, sizeof(*data));
15562306a36Sopenharmony_ci	if (ret)
15662306a36Sopenharmony_ci		goto fail;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	ret = platform_device_add(pdev);
15962306a36Sopenharmony_ci	if (ret)
16062306a36Sopenharmony_ci		goto fail;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	/* return device handle to board setup code */
16362306a36Sopenharmony_ci	data->dev = &pdev->dev;
16462306a36Sopenharmony_ci	return 0;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cifail:
16762306a36Sopenharmony_ci	platform_device_put(pdev);
16862306a36Sopenharmony_ci	return ret;
16962306a36Sopenharmony_ci}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_civoid __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
17262306a36Sopenharmony_ci			int nr_controllers)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	int i;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	for (i = 0; i < nr_controllers; i++) {
17762306a36Sopenharmony_ci		unsigned long base, size;
17862306a36Sopenharmony_ci		unsigned rx_req, tx_req;
17962306a36Sopenharmony_ci		unsigned int irq = 0;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		if (!mmc_data[i])
18262306a36Sopenharmony_ci			continue;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		omap1_mmc_mux(mmc_data[i], i);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		switch (i) {
18762306a36Sopenharmony_ci		case 0:
18862306a36Sopenharmony_ci			base = OMAP1_MMC1_BASE;
18962306a36Sopenharmony_ci			irq = INT_MMC;
19062306a36Sopenharmony_ci			rx_req = 22;
19162306a36Sopenharmony_ci			tx_req = 21;
19262306a36Sopenharmony_ci			break;
19362306a36Sopenharmony_ci		case 1:
19462306a36Sopenharmony_ci			if (!cpu_is_omap16xx())
19562306a36Sopenharmony_ci				return;
19662306a36Sopenharmony_ci			base = OMAP1_MMC2_BASE;
19762306a36Sopenharmony_ci			irq = INT_1610_MMC2;
19862306a36Sopenharmony_ci			rx_req = 55;
19962306a36Sopenharmony_ci			tx_req = 54;
20062306a36Sopenharmony_ci			break;
20162306a36Sopenharmony_ci		default:
20262306a36Sopenharmony_ci			continue;
20362306a36Sopenharmony_ci		}
20462306a36Sopenharmony_ci		size = OMAP1_MMC_SIZE;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci		omap_mmc_add("mmci-omap", i, base, size, irq,
20762306a36Sopenharmony_ci				rx_req, tx_req, mmc_data[i]);
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci#endif
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci/* Numbering for the SPI-capable controllers when used for SPI:
21662306a36Sopenharmony_ci * spi		= 1
21762306a36Sopenharmony_ci * uwire	= 2
21862306a36Sopenharmony_ci * mmc1..2	= 3..4
21962306a36Sopenharmony_ci * mcbsp1..3	= 5..7
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SPI_OMAP_UWIRE)
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci#define	OMAP_UWIRE_BASE		0xfffb3000
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic struct resource uwire_resources[] = {
22762306a36Sopenharmony_ci	{
22862306a36Sopenharmony_ci		.start		= OMAP_UWIRE_BASE,
22962306a36Sopenharmony_ci		.end		= OMAP_UWIRE_BASE + 0x20,
23062306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
23162306a36Sopenharmony_ci	},
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic struct platform_device omap_uwire_device = {
23562306a36Sopenharmony_ci	.name	   = "omap_uwire",
23662306a36Sopenharmony_ci	.id	     = -1,
23762306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(uwire_resources),
23862306a36Sopenharmony_ci	.resource	= uwire_resources,
23962306a36Sopenharmony_ci};
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic void omap_init_uwire(void)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	/* FIXME define and use a boot tag; not all boards will be hooking
24462306a36Sopenharmony_ci	 * up devices to the microwire controller, and multi-board configs
24562306a36Sopenharmony_ci	 * mean that CONFIG_SPI_OMAP_UWIRE may be configured anyway...
24662306a36Sopenharmony_ci	 */
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	/* board-specific code must configure chipselects (only a few
24962306a36Sopenharmony_ci	 * are normally used) and SCLK/SDI/SDO (each has two choices).
25062306a36Sopenharmony_ci	 */
25162306a36Sopenharmony_ci	(void) platform_device_register(&omap_uwire_device);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci#else
25462306a36Sopenharmony_cistatic inline void omap_init_uwire(void) {}
25562306a36Sopenharmony_ci#endif
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci#define OMAP1_RNG_BASE		0xfffe5000
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic struct resource omap1_rng_resources[] = {
26162306a36Sopenharmony_ci	{
26262306a36Sopenharmony_ci		.start		= OMAP1_RNG_BASE,
26362306a36Sopenharmony_ci		.end		= OMAP1_RNG_BASE + 0x4f,
26462306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
26562306a36Sopenharmony_ci	},
26662306a36Sopenharmony_ci};
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic struct platform_device omap1_rng_device = {
26962306a36Sopenharmony_ci	.name		= "omap_rng",
27062306a36Sopenharmony_ci	.id		= -1,
27162306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(omap1_rng_resources),
27262306a36Sopenharmony_ci	.resource	= omap1_rng_resources,
27362306a36Sopenharmony_ci};
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic void omap1_init_rng(void)
27662306a36Sopenharmony_ci{
27762306a36Sopenharmony_ci	if (!cpu_is_omap16xx())
27862306a36Sopenharmony_ci		return;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	(void) platform_device_register(&omap1_rng_device);
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci/*-------------------------------------------------------------------------*/
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/*
28662306a36Sopenharmony_ci * This gets called after board-specific INIT_MACHINE, and initializes most
28762306a36Sopenharmony_ci * on-chip peripherals accessible on this board (except for few like USB):
28862306a36Sopenharmony_ci *
28962306a36Sopenharmony_ci *  (a) Does any "standard config" pin muxing needed.  Board-specific
29062306a36Sopenharmony_ci *	code will have muxed GPIO pins and done "nonstandard" setup;
29162306a36Sopenharmony_ci *	that code could live in the boot loader.
29262306a36Sopenharmony_ci *  (b) Populating board-specific platform_data with the data drivers
29362306a36Sopenharmony_ci *	rely on to handle wiring variations.
29462306a36Sopenharmony_ci *  (c) Creating platform devices as meaningful on this board and
29562306a36Sopenharmony_ci *	with this kernel configuration.
29662306a36Sopenharmony_ci *
29762306a36Sopenharmony_ci * Claiming GPIOs, and setting their direction and initial values, is the
29862306a36Sopenharmony_ci * responsibility of the device drivers.  So is responding to probe().
29962306a36Sopenharmony_ci *
30062306a36Sopenharmony_ci * Board-specific knowledge like creating devices or pin setup is to be
30162306a36Sopenharmony_ci * kept out of drivers as much as possible.  In particular, pin setup
30262306a36Sopenharmony_ci * may be handled by the boot loader, and drivers should expect it will
30362306a36Sopenharmony_ci * normally have been done by the time they're probed.
30462306a36Sopenharmony_ci */
30562306a36Sopenharmony_cistatic int __init omap1_init_devices(void)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	if (!cpu_class_is_omap1())
30862306a36Sopenharmony_ci		return -ENODEV;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	omap1_sram_init();
31162306a36Sopenharmony_ci	omap1_clk_late_init();
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	/* please keep these calls, and their implementations above,
31462306a36Sopenharmony_ci	 * in alphabetical order so they're easier to sort through.
31562306a36Sopenharmony_ci	 */
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	omap_init_rtc();
31862306a36Sopenharmony_ci	omap_init_uwire();
31962306a36Sopenharmony_ci	omap1_init_rng();
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return 0;
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ciarch_initcall(omap1_init_devices);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_OMAP_WATCHDOG)
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic struct resource wdt_resources[] = {
32862306a36Sopenharmony_ci	{
32962306a36Sopenharmony_ci		.start		= 0xfffeb000,
33062306a36Sopenharmony_ci		.end		= 0xfffeb07F,
33162306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
33262306a36Sopenharmony_ci	},
33362306a36Sopenharmony_ci};
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cistatic struct platform_device omap_wdt_device = {
33662306a36Sopenharmony_ci	.name		= "omap_wdt",
33762306a36Sopenharmony_ci	.id		= -1,
33862306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(wdt_resources),
33962306a36Sopenharmony_ci	.resource	= wdt_resources,
34062306a36Sopenharmony_ci};
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic int __init omap_init_wdt(void)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	struct omap_wd_timer_platform_data pdata;
34562306a36Sopenharmony_ci	int ret;
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	if (!cpu_is_omap16xx())
34862306a36Sopenharmony_ci		return -ENODEV;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	pdata.read_reset_sources = omap1_get_reset_sources;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	ret = platform_device_register(&omap_wdt_device);
35362306a36Sopenharmony_ci	if (!ret) {
35462306a36Sopenharmony_ci		ret = platform_device_add_data(&omap_wdt_device, &pdata,
35562306a36Sopenharmony_ci					       sizeof(pdata));
35662306a36Sopenharmony_ci		if (ret)
35762306a36Sopenharmony_ci			platform_device_del(&omap_wdt_device);
35862306a36Sopenharmony_ci	}
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return ret;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_cisubsys_initcall(omap_init_wdt);
36362306a36Sopenharmony_ci#endif
364