brintos

brintos / linux-shallow public Read only

0
0
Text · 15.5 KiB · 509713b Raw
603 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * PCMCIA socket code for the Alchemy Db1xxx/Pb1xxx boards.4 *5 * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>6 *7 */8 9/* This is a fairly generic PCMCIA socket driver suitable for the10 * following Alchemy Development boards:11 *  Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200, Db130012 *13 * The Db1000 is used as a reference:  Per-socket card-, carddetect- and14 *  statuschange IRQs connected to SoC GPIOs, control and status register15 *  bits arranged in per-socket groups in an external PLD.  All boards16 *  listed here use this layout, including bit positions and meanings.17 *  Of course there are exceptions in later boards:18 *19 *	- Pb1100/Pb1500:  single socket only; voltage key bits VS are20 *			  at STATUS[5:4] (instead of STATUS[1:0]).21 *	- Au1200-based:	  additional card-eject irqs, irqs not gpios!22 *	- Db1300:	  Db1200-like, no pwr ctrl, single socket (#1).23 */24 25#include <linux/delay.h>26#include <linux/gpio.h>27#include <linux/interrupt.h>28#include <linux/pm.h>29#include <linux/module.h>30#include <linux/platform_device.h>31#include <linux/resource.h>32#include <linux/slab.h>33#include <linux/spinlock.h>34 35#include <pcmcia/ss.h>36 37#include <asm/mach-au1x00/au1000.h>38#include <asm/mach-db1x00/bcsr.h>39 40#define MEM_MAP_SIZE	0x40000041#define IO_MAP_SIZE	0x100042 43struct db1x_pcmcia_sock {44	struct pcmcia_socket	socket;45	int		nr;		/* socket number */46	void		*virt_io;47 48	phys_addr_t	phys_io;49	phys_addr_t	phys_attr;50	phys_addr_t	phys_mem;51 52	/* previous flags for set_socket() */53	unsigned int old_flags;54 55	/* interrupt sources: linux irq numbers! */56	int	insert_irq;	/* default carddetect irq */57	int	stschg_irq;	/* card-status-change irq */58	int	card_irq;	/* card irq */59	int	eject_irq;	/* db1200/pb1200 have these */60	int	insert_gpio;	/* db1000 carddetect gpio */61 62#define BOARD_TYPE_DEFAULT	0	/* most boards */63#define BOARD_TYPE_DB1200	1	/* IRQs aren't gpios */64#define BOARD_TYPE_PB1100	2	/* VS bits slightly different */65#define BOARD_TYPE_DB1300	3	/* no power control */66	int	board_type;67};68 69#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)70 71static int db1300_card_inserted(struct db1x_pcmcia_sock *sock)72{73	return bcsr_read(BCSR_SIGSTAT) & (1 << 8);74}75 76/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */77static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)78{79	unsigned short sigstat;80 81	sigstat = bcsr_read(BCSR_SIGSTAT);82	return sigstat & 1 << (8 + 2 * sock->nr);83}84 85/* carddetect gpio: low-active */86static int db1000_card_inserted(struct db1x_pcmcia_sock *sock)87{88	return !gpio_get_value(sock->insert_gpio);89}90 91static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)92{93	switch (sock->board_type) {94	case BOARD_TYPE_DB1200:95		return db1200_card_inserted(sock);96	case BOARD_TYPE_DB1300:97		return db1300_card_inserted(sock);98	default:99		return db1000_card_inserted(sock);100	}101}102 103/* STSCHG tends to bounce heavily when cards are inserted/ejected.104 * To avoid this, the interrupt is normally disabled and only enabled105 * after reset to a card has been de-asserted.106 */107static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en)108{109	if (sock->stschg_irq != -1) {110		if (en)111			enable_irq(sock->stschg_irq);112		else113			disable_irq(sock->stschg_irq);114	}115}116 117static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data)118{119	struct db1x_pcmcia_sock *sock = data;120 121	pcmcia_parse_events(&sock->socket, SS_DETECT);122 123	return IRQ_HANDLED;124}125 126static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data)127{128	struct db1x_pcmcia_sock *sock = data;129 130	pcmcia_parse_events(&sock->socket, SS_STSCHG);131 132	return IRQ_HANDLED;133}134 135/* Db/Pb1200 have separate per-socket insertion and ejection136 * interrupts which stay asserted as long as the card is137 * inserted/missing.  The one which caused us to be called138 * needs to be disabled and the other one enabled.139 */140static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data)141{142	disable_irq_nosync(irq);143	return IRQ_WAKE_THREAD;144}145 146static irqreturn_t db1200_pcmcia_cdirq_fn(int irq, void *data)147{148	struct db1x_pcmcia_sock *sock = data;149 150	/* Wait a bit for the signals to stop bouncing. */151	msleep(100);152	if (irq == sock->insert_irq)153		enable_irq(sock->eject_irq);154	else155		enable_irq(sock->insert_irq);156 157	pcmcia_parse_events(&sock->socket, SS_DETECT);158 159	return IRQ_HANDLED;160}161 162static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)163{164	int ret;165 166	if (sock->stschg_irq != -1) {167		ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq,168				  0, "pcmcia_stschg", sock);169		if (ret)170			return ret;171	}172 173	/* Db/Pb1200 have separate per-socket insertion and ejection174	 * interrupts, which should show edge behaviour but don't.175	 * So interrupts are disabled until both insertion and176	 * ejection handler have been registered and the currently177	 * active one disabled.178	 */179	if ((sock->board_type == BOARD_TYPE_DB1200) ||180	    (sock->board_type == BOARD_TYPE_DB1300)) {181		ret = request_threaded_irq(sock->insert_irq, db1200_pcmcia_cdirq,182			db1200_pcmcia_cdirq_fn, 0, "pcmcia_insert", sock);183		if (ret)184			goto out1;185 186		ret = request_threaded_irq(sock->eject_irq, db1200_pcmcia_cdirq,187			db1200_pcmcia_cdirq_fn, 0, "pcmcia_eject", sock);188		if (ret) {189			free_irq(sock->insert_irq, sock);190			goto out1;191		}192 193		/* enable the currently silent one */194		if (db1x_card_inserted(sock))195			enable_irq(sock->eject_irq);196		else197			enable_irq(sock->insert_irq);198	} else {199		/* all other (older) Db1x00 boards use a GPIO to show200		 * card detection status:  use both-edge triggers.201		 */202		irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);203		ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,204				  0, "pcmcia_carddetect", sock);205 206		if (ret)207			goto out1;208	}209 210	return 0;	/* all done */211 212out1:213	if (sock->stschg_irq != -1)214		free_irq(sock->stschg_irq, sock);215 216	return ret;217}218 219static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock)220{221	if (sock->stschg_irq != -1)222		free_irq(sock->stschg_irq, sock);223 224	free_irq(sock->insert_irq, sock);225	if (sock->eject_irq != -1)226		free_irq(sock->eject_irq, sock);227}228 229/*230 * configure a PCMCIA socket on the Db1x00 series of boards (and231 * compatibles).232 *233 * 2 external registers are involved:234 *   pcmcia_status (offset 0x04): bits [0:1/2:3]: read card voltage id235 *   pcmcia_control(offset 0x10):236 *	bits[0:1] set vcc for card237 *	bits[2:3] set vpp for card238 *	bit 4:	enable data buffers239 *	bit 7:	reset# for card240 *	add 8 for second socket.241 */242static int db1x_pcmcia_configure(struct pcmcia_socket *skt,243				 struct socket_state_t *state)244{245	struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);246	unsigned short cr_clr, cr_set;247	unsigned int changed;248	int v, p, ret;249 250	/* card voltage setup */251	cr_clr = (0xf << (sock->nr * 8)); /* clear voltage settings */252	cr_set = 0;253	v = p = ret = 0;254 255	switch (state->Vcc) {256	case 50:257		++v;258		fallthrough;259	case 33:260		++v;261		fallthrough;262	case 0:263		break;264	default:265		printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n",266			sock->nr, state->Vcc);267	}268 269	switch (state->Vpp) {270	case 12:271		++p;272		fallthrough;273	case 33:274	case 50:275		++p;276		fallthrough;277	case 0:278		break;279	default:280		printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n",281			sock->nr, state->Vpp);282	}283 284	/* sanity check: Vpp must be 0, 12, or Vcc */285	if (((state->Vcc == 33) && (state->Vpp == 50)) ||286	    ((state->Vcc == 50) && (state->Vpp == 33))) {287		printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n",288			sock->nr, state->Vcc, state->Vpp);289		v = p = 0;290		ret = -EINVAL;291	}292 293	/* create new voltage code */294	if (sock->board_type != BOARD_TYPE_DB1300)295		cr_set |= ((v << 2) | p) << (sock->nr * 8);296 297	changed = state->flags ^ sock->old_flags;298 299	if (changed & SS_RESET) {300		if (state->flags & SS_RESET) {301			set_stschg(sock, 0);302			/* assert reset, disable io buffers */303			cr_clr |= (1 << (7 + (sock->nr * 8)));304			cr_clr |= (1 << (4 + (sock->nr * 8)));305		} else {306			/* de-assert reset, enable io buffers */307			cr_set |= 1 << (7 + (sock->nr * 8));308			cr_set |= 1 << (4 + (sock->nr * 8));309		}310	}311 312	/* update PCMCIA configuration */313	bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set);314 315	sock->old_flags = state->flags;316 317	/* reset was taken away: give card time to initialize properly */318	if ((changed & SS_RESET) && !(state->flags & SS_RESET)) {319		msleep(500);320		set_stschg(sock, 1);321	}322 323	return ret;324}325 326/* VCC bits at [3:2]/[11:10] */327#define GET_VCC(cr, socknr)		\328	((((cr) >> 2) >> ((socknr) * 8)) & 3)329 330/* VS bits at [0:1]/[3:2] */331#define GET_VS(sr, socknr)		\332	(((sr) >> (2 * (socknr))) & 3)333 334/* reset bits at [7]/[15] */335#define GET_RESET(cr, socknr)		\336	((cr) & (1 << (7 + (8 * (socknr)))))337 338static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,339				  unsigned int *value)340{341	struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);342	unsigned short cr, sr;343	unsigned int status;344 345	status = db1x_card_inserted(sock) ? SS_DETECT : 0;346 347	cr = bcsr_read(BCSR_PCMCIA);348	sr = bcsr_read(BCSR_STATUS);349 350	/* PB1100/PB1500: voltage key bits are at [5:4] */351	if (sock->board_type == BOARD_TYPE_PB1100)352		sr >>= 4;353 354	/* determine card type */355	switch (GET_VS(sr, sock->nr)) {356	case 0:357	case 2:358		status |= SS_3VCARD;	/* 3V card */359		break;360	case 3:361		break;			/* 5V card: set nothing */362	default:363		status |= SS_XVCARD;	/* treated as unsupported in core */364	}365 366	/* if Vcc is not zero, we have applied power to a card */367	status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;368 369	/* DB1300: power always on, but don't tell when no card present */370	if ((sock->board_type == BOARD_TYPE_DB1300) && (status & SS_DETECT))371		status = SS_POWERON | SS_3VCARD | SS_DETECT;372 373	/* reset de-asserted? then we're ready */374	status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;375 376	*value = status;377 378	return 0;379}380 381static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt)382{383	return 0;384}385 386static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt)387{388	return 0;389}390 391static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,392				    struct pccard_io_map *map)393{394	struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);395 396	map->start = (u32)sock->virt_io;397	map->stop = map->start + IO_MAP_SIZE;398 399	return 0;400}401 402static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,403				     struct pccard_mem_map *map)404{405	struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);406 407	if (map->flags & MAP_ATTRIB)408		map->static_start = sock->phys_attr + map->card_start;409	else410		map->static_start = sock->phys_mem + map->card_start;411 412	return 0;413}414 415static struct pccard_operations db1x_pcmcia_operations = {416	.init			= db1x_pcmcia_sock_init,417	.suspend		= db1x_pcmcia_sock_suspend,418	.get_status		= db1x_pcmcia_get_status,419	.set_socket		= db1x_pcmcia_configure,420	.set_io_map		= au1x00_pcmcia_set_io_map,421	.set_mem_map		= au1x00_pcmcia_set_mem_map,422};423 424static int db1x_pcmcia_socket_probe(struct platform_device *pdev)425{426	struct db1x_pcmcia_sock *sock;427	struct resource *r;428	int ret, bid;429 430	sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL);431	if (!sock)432		return -ENOMEM;433 434	sock->nr = pdev->id;435 436	bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));437	switch (bid) {438	case BCSR_WHOAMI_PB1500:439	case BCSR_WHOAMI_PB1500R2:440	case BCSR_WHOAMI_PB1100:441		sock->board_type = BOARD_TYPE_PB1100;442		break;443	case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR:444		sock->board_type = BOARD_TYPE_DEFAULT;445		break;446	case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:447		sock->board_type = BOARD_TYPE_DB1200;448		break;449	case BCSR_WHOAMI_DB1300:450		sock->board_type = BOARD_TYPE_DB1300;451		break;452	default:453		printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);454		ret = -ENODEV;455		goto out0;456	}457 458	/*459	 * gather resources necessary and optional nice-to-haves to460	 * operate a socket:461	 * This includes IRQs for Carddetection/ejection, the card462	 *  itself and optional status change detection.463	 * Also, the memory areas covered by a socket.  For these464	 *  we require the real 36bit addresses (see the au1000.h465	 *  header for more information).466	 */467 468	/* card: irq assigned to the card itself. */469	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");470	sock->card_irq = r ? r->start : 0;471 472	/* insert: irq which triggers on card insertion/ejection473	 * BIG FAT NOTE: on DB1000/1100/1500/1550 we pass a GPIO here!474	 */475	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert");476	sock->insert_irq = r ? r->start : -1;477	if (sock->board_type == BOARD_TYPE_DEFAULT) {478		sock->insert_gpio = r ? r->start : -1;479		sock->insert_irq = r ? gpio_to_irq(r->start) : -1;480	}481 482	/* stschg: irq which trigger on card status change (optional) */483	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");484	sock->stschg_irq = r ? r->start : -1;485 486	/* eject: irq which triggers on ejection (DB1200/PB1200 only) */487	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject");488	sock->eject_irq = r ? r->start : -1;489 490	ret = -ENODEV;491 492	/* 36bit PCMCIA Attribute area address */493	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");494	if (!r) {495		printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",496			sock->nr);497		goto out0;498	}499	sock->phys_attr = r->start;500 501	/* 36bit PCMCIA Memory area address */502	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");503	if (!r) {504		printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",505			sock->nr);506		goto out0;507	}508	sock->phys_mem = r->start;509 510	/* 36bit PCMCIA IO area address */511	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");512	if (!r) {513		printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",514			sock->nr);515		goto out0;516	}517	sock->phys_io = r->start;518 519	/*520	 * PCMCIA client drivers use the inb/outb macros to access521	 * the IO registers.  Since mips_io_port_base is added522	 * to the access address of the mips implementation of523	 * inb/outb, we need to subtract it here because we want524	 * to access the I/O or MEM address directly, without525	 * going through this "mips_io_port_base" mechanism.526	 */527	sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -528				 mips_io_port_base);529 530	if (!sock->virt_io) {531		printk(KERN_ERR "pcmcia%d: cannot remap IO area\n",532			sock->nr);533		ret = -ENOMEM;534		goto out0;535	}536 537	sock->socket.ops	= &db1x_pcmcia_operations;538	sock->socket.owner	= THIS_MODULE;539	sock->socket.pci_irq	= sock->card_irq;540	sock->socket.features	= SS_CAP_STATIC_MAP | SS_CAP_PCCARD;541	sock->socket.map_size	= MEM_MAP_SIZE;542	sock->socket.io_offset	= (unsigned long)sock->virt_io;543	sock->socket.dev.parent	= &pdev->dev;544	sock->socket.resource_ops = &pccard_static_ops;545 546	platform_set_drvdata(pdev, sock);547 548	ret = db1x_pcmcia_setup_irqs(sock);549	if (ret) {550		printk(KERN_ERR "pcmcia%d cannot setup interrupts\n",551			sock->nr);552		goto out1;553	}554 555	set_stschg(sock, 0);556 557	ret = pcmcia_register_socket(&sock->socket);558	if (ret) {559		printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr);560		goto out2;561	}562 563	printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx"564		"(%p) %09llx %09llx  card/insert/stschg/eject irqs @ %d "565		"%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io,566		sock->phys_attr, sock->phys_mem, sock->card_irq,567		sock->insert_irq, sock->stschg_irq, sock->eject_irq);568 569	return 0;570 571out2:572	db1x_pcmcia_free_irqs(sock);573out1:574	iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));575out0:576	kfree(sock);577	return ret;578}579 580static void db1x_pcmcia_socket_remove(struct platform_device *pdev)581{582	struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);583 584	db1x_pcmcia_free_irqs(sock);585	pcmcia_unregister_socket(&sock->socket);586	iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));587	kfree(sock);588}589 590static struct platform_driver db1x_pcmcia_socket_driver = {591	.driver	= {592		.name	= "db1xxx_pcmcia",593	},594	.probe		= db1x_pcmcia_socket_probe,595	.remove_new	= db1x_pcmcia_socket_remove,596};597 598module_platform_driver(db1x_pcmcia_socket_driver);599 600MODULE_LICENSE("GPL");601MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");602MODULE_AUTHOR("Manuel Lauss");603