162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * linux/arch/arm/mach-omap2/board-n8x0.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005-2009 Nokia Corporation
662306a36Sopenharmony_ci * Author: Juha Yrjola <juha.yrjola@nokia.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Modified from mach-omap2/board-generic.c
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/clk.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/gpio/machine.h>
1462306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1562306a36Sopenharmony_ci#include <linux/init.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/irq.h>
1862306a36Sopenharmony_ci#include <linux/stddef.h>
1962306a36Sopenharmony_ci#include <linux/i2c.h>
2062306a36Sopenharmony_ci#include <linux/spi/spi.h>
2162306a36Sopenharmony_ci#include <linux/usb/musb.h>
2262306a36Sopenharmony_ci#include <linux/mmc/host.h>
2362306a36Sopenharmony_ci#include <linux/platform_data/spi-omap2-mcspi.h>
2462306a36Sopenharmony_ci#include <linux/platform_data/mmc-omap.h>
2562306a36Sopenharmony_ci#include <linux/mfd/menelaus.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <asm/mach/arch.h>
2862306a36Sopenharmony_ci#include <asm/mach-types.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "common.h"
3162306a36Sopenharmony_ci#include "mmc.h"
3262306a36Sopenharmony_ci#include "usb-tusb6010.h"
3362306a36Sopenharmony_ci#include "soc.h"
3462306a36Sopenharmony_ci#include "common-board-devices.h"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define TUSB6010_ASYNC_CS	1
3762306a36Sopenharmony_ci#define TUSB6010_SYNC_CS	4
3862306a36Sopenharmony_ci#define TUSB6010_DMACHAN	0x3f
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#define NOKIA_N810_WIMAX	(1 << 2)
4162306a36Sopenharmony_ci#define NOKIA_N810		(1 << 1)
4262306a36Sopenharmony_ci#define NOKIA_N800		(1 << 0)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic u32 board_caps;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define board_is_n800()		(board_caps & NOKIA_N800)
4762306a36Sopenharmony_ci#define board_is_n810()		(board_caps & NOKIA_N810)
4862306a36Sopenharmony_ci#define board_is_n810_wimax()	(board_caps & NOKIA_N810_WIMAX)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void board_check_revision(void)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	if (of_machine_is_compatible("nokia,n800"))
5362306a36Sopenharmony_ci		board_caps = NOKIA_N800;
5462306a36Sopenharmony_ci	else if (of_machine_is_compatible("nokia,n810"))
5562306a36Sopenharmony_ci		board_caps = NOKIA_N810;
5662306a36Sopenharmony_ci	else if (of_machine_is_compatible("nokia,n810-wimax"))
5762306a36Sopenharmony_ci		board_caps = NOKIA_N810_WIMAX;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	if (!board_caps)
6062306a36Sopenharmony_ci		pr_err("Unknown board\n");
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010)
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic struct musb_hdrc_config musb_config = {
6662306a36Sopenharmony_ci	.multipoint	= 1,
6762306a36Sopenharmony_ci	.dyn_fifo	= 1,
6862306a36Sopenharmony_ci	.num_eps	= 16,
6962306a36Sopenharmony_ci	.ram_bits	= 12,
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic struct musb_hdrc_platform_data tusb_data = {
7362306a36Sopenharmony_ci	.mode		= MUSB_OTG,
7462306a36Sopenharmony_ci	.min_power	= 25,	/* x2 = 50 mA drawn from VBUS as peripheral */
7562306a36Sopenharmony_ci	.power		= 100,	/* Max 100 mA VBUS for host mode */
7662306a36Sopenharmony_ci	.config		= &musb_config,
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic struct gpiod_lookup_table tusb_gpio_table = {
8062306a36Sopenharmony_ci	.dev_id = "musb-tusb",
8162306a36Sopenharmony_ci	.table = {
8262306a36Sopenharmony_ci		GPIO_LOOKUP("gpio-0-15", 0, "enable",
8362306a36Sopenharmony_ci			    GPIO_ACTIVE_HIGH),
8462306a36Sopenharmony_ci		GPIO_LOOKUP("gpio-48-63", 10, "int",
8562306a36Sopenharmony_ci			    GPIO_ACTIVE_HIGH),
8662306a36Sopenharmony_ci		{ }
8762306a36Sopenharmony_ci	},
8862306a36Sopenharmony_ci};
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic void __init n8x0_usb_init(void)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	int ret = 0;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	gpiod_add_lookup_table(&tusb_gpio_table);
9562306a36Sopenharmony_ci	ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2,
9662306a36Sopenharmony_ci				       TUSB6010_ASYNC_CS, TUSB6010_SYNC_CS,
9762306a36Sopenharmony_ci				       TUSB6010_DMACHAN);
9862306a36Sopenharmony_ci	if (ret != 0)
9962306a36Sopenharmony_ci		return;
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	pr_info("TUSB 6010\n");
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	return;
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci#else
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic void __init n8x0_usb_init(void) {}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci#endif /*CONFIG_USB_MUSB_TUSB6010 */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic struct omap2_mcspi_device_config p54spi_mcspi_config = {
11362306a36Sopenharmony_ci	.turbo_mode	= 0,
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic struct spi_board_info n800_spi_board_info[] __initdata = {
11762306a36Sopenharmony_ci	{
11862306a36Sopenharmony_ci		.modalias	= "p54spi",
11962306a36Sopenharmony_ci		.bus_num	= 2,
12062306a36Sopenharmony_ci		.chip_select	= 0,
12162306a36Sopenharmony_ci		.max_speed_hz   = 48000000,
12262306a36Sopenharmony_ci		.controller_data = &p54spi_mcspi_config,
12362306a36Sopenharmony_ci	},
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci#if defined(CONFIG_MENELAUS) && IS_ENABLED(CONFIG_MMC_OMAP)
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/*
12962306a36Sopenharmony_ci * On both N800 and N810, only the first of the two MMC controllers is in use.
13062306a36Sopenharmony_ci * The two MMC slots are multiplexed via Menelaus companion chip over I2C.
13162306a36Sopenharmony_ci * On N800, both slots are powered via Menelaus. On N810, only one of the
13262306a36Sopenharmony_ci * slots is powered via Menelaus. The N810 EMMC is powered via GPIO.
13362306a36Sopenharmony_ci *
13462306a36Sopenharmony_ci * VMMC				slot 1 on both N800 and N810
13562306a36Sopenharmony_ci * VDCDC3_APE and VMCS2_APE	slot 2 on N800
13662306a36Sopenharmony_ci * GPIO23 and GPIO9		slot 2 EMMC on N810
13762306a36Sopenharmony_ci *
13862306a36Sopenharmony_ci */
13962306a36Sopenharmony_cistatic int slot1_cover_open;
14062306a36Sopenharmony_cistatic int slot2_cover_open;
14162306a36Sopenharmony_cistatic struct device *mmc_device;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
14462306a36Sopenharmony_ci	.dev_id = "mmci-omap.0",
14562306a36Sopenharmony_ci	.table = {
14662306a36Sopenharmony_ci		/* Slot switch, GPIO 96 */
14762306a36Sopenharmony_ci		GPIO_LOOKUP("gpio-80-111", 16,
14862306a36Sopenharmony_ci			    "switch", GPIO_ACTIVE_HIGH),
14962306a36Sopenharmony_ci		{ }
15062306a36Sopenharmony_ci	},
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_cistatic struct gpiod_lookup_table nokia810_mmc_gpio_table = {
15462306a36Sopenharmony_ci	.dev_id = "mmci-omap.0",
15562306a36Sopenharmony_ci	.table = {
15662306a36Sopenharmony_ci		/* Slot index 1, VSD power, GPIO 23 */
15762306a36Sopenharmony_ci		GPIO_LOOKUP_IDX("gpio-16-31", 7,
15862306a36Sopenharmony_ci				"vsd", 1, GPIO_ACTIVE_HIGH),
15962306a36Sopenharmony_ci		/* Slot index 1, VIO power, GPIO 9 */
16062306a36Sopenharmony_ci		GPIO_LOOKUP_IDX("gpio-0-15", 9,
16162306a36Sopenharmony_ci				"vio", 1, GPIO_ACTIVE_HIGH),
16262306a36Sopenharmony_ci		{ }
16362306a36Sopenharmony_ci	},
16462306a36Sopenharmony_ci};
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic int n8x0_mmc_set_power_menelaus(struct device *dev, int slot,
16762306a36Sopenharmony_ci					int power_on, int vdd)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	int mV;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci#ifdef CONFIG_MMC_DEBUG
17262306a36Sopenharmony_ci	dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1,
17362306a36Sopenharmony_ci		power_on ? "on" : "off", vdd);
17462306a36Sopenharmony_ci#endif
17562306a36Sopenharmony_ci	if (slot == 0) {
17662306a36Sopenharmony_ci		if (!power_on)
17762306a36Sopenharmony_ci			return menelaus_set_vmmc(0);
17862306a36Sopenharmony_ci		switch (1 << vdd) {
17962306a36Sopenharmony_ci		case MMC_VDD_33_34:
18062306a36Sopenharmony_ci		case MMC_VDD_32_33:
18162306a36Sopenharmony_ci		case MMC_VDD_31_32:
18262306a36Sopenharmony_ci			mV = 3100;
18362306a36Sopenharmony_ci			break;
18462306a36Sopenharmony_ci		case MMC_VDD_30_31:
18562306a36Sopenharmony_ci			mV = 3000;
18662306a36Sopenharmony_ci			break;
18762306a36Sopenharmony_ci		case MMC_VDD_28_29:
18862306a36Sopenharmony_ci			mV = 2800;
18962306a36Sopenharmony_ci			break;
19062306a36Sopenharmony_ci		case MMC_VDD_165_195:
19162306a36Sopenharmony_ci			mV = 1850;
19262306a36Sopenharmony_ci			break;
19362306a36Sopenharmony_ci		default:
19462306a36Sopenharmony_ci			BUG();
19562306a36Sopenharmony_ci		}
19662306a36Sopenharmony_ci		return menelaus_set_vmmc(mV);
19762306a36Sopenharmony_ci	} else {
19862306a36Sopenharmony_ci		if (!power_on)
19962306a36Sopenharmony_ci			return menelaus_set_vdcdc(3, 0);
20062306a36Sopenharmony_ci		switch (1 << vdd) {
20162306a36Sopenharmony_ci		case MMC_VDD_33_34:
20262306a36Sopenharmony_ci		case MMC_VDD_32_33:
20362306a36Sopenharmony_ci			mV = 3300;
20462306a36Sopenharmony_ci			break;
20562306a36Sopenharmony_ci		case MMC_VDD_30_31:
20662306a36Sopenharmony_ci		case MMC_VDD_29_30:
20762306a36Sopenharmony_ci			mV = 3000;
20862306a36Sopenharmony_ci			break;
20962306a36Sopenharmony_ci		case MMC_VDD_28_29:
21062306a36Sopenharmony_ci		case MMC_VDD_27_28:
21162306a36Sopenharmony_ci			mV = 2800;
21262306a36Sopenharmony_ci			break;
21362306a36Sopenharmony_ci		case MMC_VDD_24_25:
21462306a36Sopenharmony_ci		case MMC_VDD_23_24:
21562306a36Sopenharmony_ci			mV = 2400;
21662306a36Sopenharmony_ci			break;
21762306a36Sopenharmony_ci		case MMC_VDD_22_23:
21862306a36Sopenharmony_ci		case MMC_VDD_21_22:
21962306a36Sopenharmony_ci			mV = 2200;
22062306a36Sopenharmony_ci			break;
22162306a36Sopenharmony_ci		case MMC_VDD_20_21:
22262306a36Sopenharmony_ci			mV = 2000;
22362306a36Sopenharmony_ci			break;
22462306a36Sopenharmony_ci		case MMC_VDD_165_195:
22562306a36Sopenharmony_ci			mV = 1800;
22662306a36Sopenharmony_ci			break;
22762306a36Sopenharmony_ci		default:
22862306a36Sopenharmony_ci			BUG();
22962306a36Sopenharmony_ci		}
23062306a36Sopenharmony_ci		return menelaus_set_vdcdc(3, mV);
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci	return 0;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int n8x0_mmc_set_power(struct device *dev, int slot, int power_on,
23662306a36Sopenharmony_ci			      int vdd)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	if (board_is_n800() || slot == 0)
23962306a36Sopenharmony_ci		return n8x0_mmc_set_power_menelaus(dev, slot, power_on, vdd);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	/* The n810 power will be handled by GPIO code in the driver */
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return 0;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic int n8x0_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci	int r;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1,
25162306a36Sopenharmony_ci		bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull");
25262306a36Sopenharmony_ci	BUG_ON(slot != 0 && slot != 1);
25362306a36Sopenharmony_ci	slot++;
25462306a36Sopenharmony_ci	switch (bus_mode) {
25562306a36Sopenharmony_ci	case MMC_BUSMODE_OPENDRAIN:
25662306a36Sopenharmony_ci		r = menelaus_set_mmc_opendrain(slot, 1);
25762306a36Sopenharmony_ci		break;
25862306a36Sopenharmony_ci	case MMC_BUSMODE_PUSHPULL:
25962306a36Sopenharmony_ci		r = menelaus_set_mmc_opendrain(slot, 0);
26062306a36Sopenharmony_ci		break;
26162306a36Sopenharmony_ci	default:
26262306a36Sopenharmony_ci		BUG();
26362306a36Sopenharmony_ci	}
26462306a36Sopenharmony_ci	if (r != 0 && printk_ratelimit())
26562306a36Sopenharmony_ci		dev_err(dev, "MMC: unable to set bus mode for slot %d\n",
26662306a36Sopenharmony_ci			slot);
26762306a36Sopenharmony_ci	return r;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic int n8x0_mmc_get_cover_state(struct device *dev, int slot)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	slot++;
27362306a36Sopenharmony_ci	BUG_ON(slot != 1 && slot != 2);
27462306a36Sopenharmony_ci	if (slot == 1)
27562306a36Sopenharmony_ci		return slot1_cover_open;
27662306a36Sopenharmony_ci	else
27762306a36Sopenharmony_ci		return slot2_cover_open;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic void n8x0_mmc_callback(void *data, u8 card_mask)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci#ifdef CONFIG_MMC_OMAP
28362306a36Sopenharmony_ci	int bit, *openp, index;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (board_is_n800()) {
28662306a36Sopenharmony_ci		bit = 1 << 1;
28762306a36Sopenharmony_ci		openp = &slot2_cover_open;
28862306a36Sopenharmony_ci		index = 1;
28962306a36Sopenharmony_ci	} else {
29062306a36Sopenharmony_ci		bit = 1;
29162306a36Sopenharmony_ci		openp = &slot1_cover_open;
29262306a36Sopenharmony_ci		index = 0;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	if (card_mask & bit)
29662306a36Sopenharmony_ci		*openp = 1;
29762306a36Sopenharmony_ci	else
29862306a36Sopenharmony_ci		*openp = 0;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	omap_mmc_notify_cover_event(mmc_device, index, *openp);
30162306a36Sopenharmony_ci#else
30262306a36Sopenharmony_ci	pr_warn("MMC: notify cover event not available\n");
30362306a36Sopenharmony_ci#endif
30462306a36Sopenharmony_ci}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_cistatic int n8x0_mmc_late_init(struct device *dev)
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	int r, bit, *openp;
30962306a36Sopenharmony_ci	int vs2sel;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	mmc_device = dev;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	r = menelaus_set_slot_sel(1);
31462306a36Sopenharmony_ci	if (r < 0)
31562306a36Sopenharmony_ci		return r;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	if (board_is_n800())
31862306a36Sopenharmony_ci		vs2sel = 0;
31962306a36Sopenharmony_ci	else
32062306a36Sopenharmony_ci		vs2sel = 2;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	r = menelaus_set_mmc_slot(2, 0, vs2sel, 1);
32362306a36Sopenharmony_ci	if (r < 0)
32462306a36Sopenharmony_ci		return r;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	n8x0_mmc_set_power(dev, 0, MMC_POWER_ON, 16); /* MMC_VDD_28_29 */
32762306a36Sopenharmony_ci	n8x0_mmc_set_power(dev, 1, MMC_POWER_ON, 16);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	r = menelaus_set_mmc_slot(1, 1, 0, 1);
33062306a36Sopenharmony_ci	if (r < 0)
33162306a36Sopenharmony_ci		return r;
33262306a36Sopenharmony_ci	r = menelaus_set_mmc_slot(2, 1, vs2sel, 1);
33362306a36Sopenharmony_ci	if (r < 0)
33462306a36Sopenharmony_ci		return r;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	r = menelaus_get_slot_pin_states();
33762306a36Sopenharmony_ci	if (r < 0)
33862306a36Sopenharmony_ci		return r;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	if (board_is_n800()) {
34162306a36Sopenharmony_ci		bit = 1 << 1;
34262306a36Sopenharmony_ci		openp = &slot2_cover_open;
34362306a36Sopenharmony_ci	} else {
34462306a36Sopenharmony_ci		bit = 1;
34562306a36Sopenharmony_ci		openp = &slot1_cover_open;
34662306a36Sopenharmony_ci		slot2_cover_open = 0;
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	/* All slot pin bits seem to be inversed until first switch change */
35062306a36Sopenharmony_ci	if (r == 0xf || r == (0xf & ~bit))
35162306a36Sopenharmony_ci		r = ~r;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (r & bit)
35462306a36Sopenharmony_ci		*openp = 1;
35562306a36Sopenharmony_ci	else
35662306a36Sopenharmony_ci		*openp = 0;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	r = menelaus_register_mmc_callback(n8x0_mmc_callback, NULL);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	return r;
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic void n8x0_mmc_shutdown(struct device *dev)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	int vs2sel;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	if (board_is_n800())
36862306a36Sopenharmony_ci		vs2sel = 0;
36962306a36Sopenharmony_ci	else
37062306a36Sopenharmony_ci		vs2sel = 2;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	menelaus_set_mmc_slot(1, 0, 0, 0);
37362306a36Sopenharmony_ci	menelaus_set_mmc_slot(2, 0, vs2sel, 0);
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_cistatic void n8x0_mmc_cleanup(struct device *dev)
37762306a36Sopenharmony_ci{
37862306a36Sopenharmony_ci	menelaus_unregister_mmc_callback();
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci/*
38262306a36Sopenharmony_ci * MMC controller1 has two slots that are multiplexed via I2C.
38362306a36Sopenharmony_ci * MMC controller2 is not in use.
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_cistatic struct omap_mmc_platform_data mmc1_data = {
38662306a36Sopenharmony_ci	.nr_slots			= 0,
38762306a36Sopenharmony_ci	.init				= n8x0_mmc_late_init,
38862306a36Sopenharmony_ci	.cleanup			= n8x0_mmc_cleanup,
38962306a36Sopenharmony_ci	.shutdown			= n8x0_mmc_shutdown,
39062306a36Sopenharmony_ci	.max_freq			= 24000000,
39162306a36Sopenharmony_ci	.slots[0] = {
39262306a36Sopenharmony_ci		.wires			= 4,
39362306a36Sopenharmony_ci		.set_power		= n8x0_mmc_set_power,
39462306a36Sopenharmony_ci		.set_bus_mode		= n8x0_mmc_set_bus_mode,
39562306a36Sopenharmony_ci		.get_cover_state	= n8x0_mmc_get_cover_state,
39662306a36Sopenharmony_ci		.ocr_mask		= MMC_VDD_165_195 | MMC_VDD_30_31 |
39762306a36Sopenharmony_ci						MMC_VDD_32_33   | MMC_VDD_33_34,
39862306a36Sopenharmony_ci		.name			= "internal",
39962306a36Sopenharmony_ci	},
40062306a36Sopenharmony_ci	.slots[1] = {
40162306a36Sopenharmony_ci		.set_power		= n8x0_mmc_set_power,
40262306a36Sopenharmony_ci		.set_bus_mode		= n8x0_mmc_set_bus_mode,
40362306a36Sopenharmony_ci		.get_cover_state	= n8x0_mmc_get_cover_state,
40462306a36Sopenharmony_ci		.ocr_mask		= MMC_VDD_165_195 | MMC_VDD_20_21 |
40562306a36Sopenharmony_ci						MMC_VDD_21_22 | MMC_VDD_22_23 |
40662306a36Sopenharmony_ci						MMC_VDD_23_24 | MMC_VDD_24_25 |
40762306a36Sopenharmony_ci						MMC_VDD_27_28 | MMC_VDD_28_29 |
40862306a36Sopenharmony_ci						MMC_VDD_29_30 | MMC_VDD_30_31 |
40962306a36Sopenharmony_ci						MMC_VDD_32_33 | MMC_VDD_33_34,
41062306a36Sopenharmony_ci		.name			= "external",
41162306a36Sopenharmony_ci	},
41262306a36Sopenharmony_ci};
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_cistatic struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic void __init n8x0_mmc_init(void)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	if (board_is_n810()) {
42162306a36Sopenharmony_ci		mmc1_data.slots[0].name = "external";
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci		/*
42462306a36Sopenharmony_ci		 * Some Samsung Movinand chips do not like open-ended
42562306a36Sopenharmony_ci		 * multi-block reads and fall to braind-dead state
42662306a36Sopenharmony_ci		 * while doing so. Reducing the number of blocks in
42762306a36Sopenharmony_ci		 * the transfer or delays in clock disable do not help
42862306a36Sopenharmony_ci		 */
42962306a36Sopenharmony_ci		mmc1_data.slots[1].name = "internal";
43062306a36Sopenharmony_ci		mmc1_data.slots[1].ban_openended = 1;
43162306a36Sopenharmony_ci		gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
43262306a36Sopenharmony_ci	}
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	mmc1_data.nr_slots = 2;
43562306a36Sopenharmony_ci	mmc_data[0] = &mmc1_data;
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci#else
43862306a36Sopenharmony_cistatic struct omap_mmc_platform_data mmc1_data;
43962306a36Sopenharmony_cistatic void __init n8x0_mmc_init(void)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci#endif	/* CONFIG_MMC_OMAP */
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci#ifdef CONFIG_MENELAUS
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic int n8x0_auto_sleep_regulators(void)
44762306a36Sopenharmony_ci{
44862306a36Sopenharmony_ci	u32 val;
44962306a36Sopenharmony_ci	int ret;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	val = EN_VPLL_SLEEP | EN_VMMC_SLEEP    \
45262306a36Sopenharmony_ci		| EN_VAUX_SLEEP | EN_VIO_SLEEP \
45362306a36Sopenharmony_ci		| EN_VMEM_SLEEP | EN_DC3_SLEEP \
45462306a36Sopenharmony_ci		| EN_VC_SLEEP | EN_DC2_SLEEP;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	ret = menelaus_set_regulator_sleep(1, val);
45762306a36Sopenharmony_ci	if (ret < 0) {
45862306a36Sopenharmony_ci		pr_err("Could not set regulators to sleep on menelaus: %u\n",
45962306a36Sopenharmony_ci		       ret);
46062306a36Sopenharmony_ci		return ret;
46162306a36Sopenharmony_ci	}
46262306a36Sopenharmony_ci	return 0;
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic int n8x0_auto_voltage_scale(void)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	int ret;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	ret = menelaus_set_vcore_hw(1400, 1050);
47062306a36Sopenharmony_ci	if (ret < 0) {
47162306a36Sopenharmony_ci		pr_err("Could not set VCORE voltage on menelaus: %u\n", ret);
47262306a36Sopenharmony_ci		return ret;
47362306a36Sopenharmony_ci	}
47462306a36Sopenharmony_ci	return 0;
47562306a36Sopenharmony_ci}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_cistatic int n8x0_menelaus_late_init(struct device *dev)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	int ret;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	ret = n8x0_auto_voltage_scale();
48262306a36Sopenharmony_ci	if (ret < 0)
48362306a36Sopenharmony_ci		return ret;
48462306a36Sopenharmony_ci	ret = n8x0_auto_sleep_regulators();
48562306a36Sopenharmony_ci	if (ret < 0)
48662306a36Sopenharmony_ci		return ret;
48762306a36Sopenharmony_ci	return 0;
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci#else
49162306a36Sopenharmony_cistatic int n8x0_menelaus_late_init(struct device *dev)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	return 0;
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci#endif
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistruct menelaus_platform_data n8x0_menelaus_platform_data = {
49862306a36Sopenharmony_ci	.late_init = n8x0_menelaus_late_init,
49962306a36Sopenharmony_ci};
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic int __init n8x0_late_initcall(void)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	if (!board_caps)
50462306a36Sopenharmony_ci		return -ENODEV;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	n8x0_mmc_init();
50762306a36Sopenharmony_ci	n8x0_usb_init();
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	return 0;
51062306a36Sopenharmony_ci}
51162306a36Sopenharmony_ciomap_late_initcall(n8x0_late_initcall);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci/*
51462306a36Sopenharmony_ci * Legacy init pdata init for n8x0. Note that we want to follow the
51562306a36Sopenharmony_ci * I2C bus numbering starting at 0 for device tree like other omaps.
51662306a36Sopenharmony_ci */
51762306a36Sopenharmony_civoid * __init n8x0_legacy_init(void)
51862306a36Sopenharmony_ci{
51962306a36Sopenharmony_ci	board_check_revision();
52062306a36Sopenharmony_ci	spi_register_board_info(n800_spi_board_info,
52162306a36Sopenharmony_ci				ARRAY_SIZE(n800_spi_board_info));
52262306a36Sopenharmony_ci	return &mmc1_data;
52362306a36Sopenharmony_ci}
524