| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 | /* * arch/arm/mach-orion5x/ts78xx-setup.c * * Maintainer: Alexander Clouter <alex@digriz.org.uk> * * This file is licensed under the terms of the GNU General Public * License version 2.  This program is licensed "as is" without any * warranty of any kind, whether express or implied. */#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt#include <linux/kernel.h>#include <linux/init.h>#include <linux/sysfs.h>#include <linux/platform_device.h>#include <linux/mv643xx_eth.h>#include <linux/ata_platform.h>#include <linux/m48t86.h>#include <linux/mtd/nand.h>#include <linux/mtd/partitions.h>#include <linux/timeriomem-rng.h>#include <asm/mach-types.h>#include <asm/mach/arch.h>#include <asm/mach/map.h>#include <mach/orion5x.h>#include "common.h"#include "mpp.h"#include "ts78xx-fpga.h"/***************************************************************************** * TS-78xx Info ****************************************************************************//* * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE */#define TS78XX_FPGA_REGS_PHYS_BASE	0xe8000000#define TS78XX_FPGA_REGS_VIRT_BASE	IOMEM(0xff900000)#define TS78XX_FPGA_REGS_SIZE		SZ_1Mstatic struct ts78xx_fpga_data ts78xx_fpga = {	.id		= 0,	.state		= 1,/*	.supports	= ... - populated by ts78xx_fpga_supports() */};/***************************************************************************** * I/O Address Mapping ****************************************************************************/static struct map_desc ts78xx_io_desc[] __initdata = {	{		.virtual	= (unsigned long)TS78XX_FPGA_REGS_VIRT_BASE,		.pfn		= __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE),		.length		= TS78XX_FPGA_REGS_SIZE,		.type		= MT_DEVICE,	},};void __init ts78xx_map_io(void){	orion5x_map_io();	iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc));}/***************************************************************************** * Ethernet ****************************************************************************/static struct mv643xx_eth_platform_data ts78xx_eth_data = {	.phy_addr	= MV643XX_ETH_PHY_ADDR(0),};/***************************************************************************** * SATA ****************************************************************************/static struct mv_sata_platform_data ts78xx_sata_data = {	.n_ports	= 2,};/***************************************************************************** * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c ****************************************************************************/#define TS_RTC_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE + 0x808)#define TS_RTC_DATA	(TS78XX_FPGA_REGS_VIRT_BASE + 0x80c)static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr){	writeb(addr, TS_RTC_CTRL);	return readb(TS_RTC_DATA);}static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr){	writeb(addr, TS_RTC_CTRL);	writeb(value, TS_RTC_DATA);}static struct m48t86_ops ts78xx_ts_rtc_ops = {	.readbyte	= ts78xx_ts_rtc_readbyte,	.writebyte	= ts78xx_ts_rtc_writebyte,};static struct platform_device ts78xx_ts_rtc_device = {	.name		= "rtc-m48t86",	.id		= -1,	.dev		= {		.platform_data	= &ts78xx_ts_rtc_ops,	},	.num_resources	= 0,};/* * TS uses some of the user storage space on the RTC chip so see if it is * present; as it's an optional feature at purchase time and not all boards * will have it present * * I've used the method TS use in their rtc7800.c example for the detection * * TODO: track down a guinea pig without an RTC to see if we can work out a *		better RTC detection routine */static int ts78xx_ts_rtc_load(void){	int rc;	unsigned char tmp_rtc0, tmp_rtc1;	tmp_rtc0 = ts78xx_ts_rtc_readbyte(126);	tmp_rtc1 = ts78xx_ts_rtc_readbyte(127);	ts78xx_ts_rtc_writebyte(0x00, 126);	ts78xx_ts_rtc_writebyte(0x55, 127);	if (ts78xx_ts_rtc_readbyte(127) == 0x55) {		ts78xx_ts_rtc_writebyte(0xaa, 127);		if (ts78xx_ts_rtc_readbyte(127) == 0xaa				&& ts78xx_ts_rtc_readbyte(126) == 0x00) {			ts78xx_ts_rtc_writebyte(tmp_rtc0, 126);			ts78xx_ts_rtc_writebyte(tmp_rtc1, 127);			if (ts78xx_fpga.supports.ts_rtc.init == 0) {				rc = platform_device_register(&ts78xx_ts_rtc_device);				if (!rc)					ts78xx_fpga.supports.ts_rtc.init = 1;			} else				rc = platform_device_add(&ts78xx_ts_rtc_device);			if (rc)				pr_info("RTC could not be registered: %d\n",					rc);			return rc;		}	}	pr_info("RTC not found\n");	return -ENODEV;};static void ts78xx_ts_rtc_unload(void){	platform_device_del(&ts78xx_ts_rtc_device);}/***************************************************************************** * NAND Flash ****************************************************************************/#define TS_NAND_CTRL	(TS78XX_FPGA_REGS_VIRT_BASE + 0x800)	/* VIRT */#define TS_NAND_DATA	(TS78XX_FPGA_REGS_PHYS_BASE + 0x804)	/* PHYS *//* * hardware specific access to control-lines * * ctrl: * NAND_NCE: bit 0 -> bit 2 * NAND_CLE: bit 1 -> bit 1 * NAND_ALE: bit 2 -> bit 0 */static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,			unsigned int ctrl){	struct nand_chip *this = mtd->priv;	if (ctrl & NAND_CTRL_CHANGE) {		unsigned char bits;		bits = (ctrl & NAND_NCE) << 2;		bits |= ctrl & NAND_CLE;		bits |= (ctrl & NAND_ALE) >> 2;		writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL);	}
 |