cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tifm_7xx1.c (10967B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  tifm_7xx1.c - TI FlashMedia driver
      4 *
      5 *  Copyright (C) 2006 Alex Dubov <oakad@yahoo.com>
      6 */
      7
      8#include <linux/tifm.h>
      9#include <linux/dma-mapping.h>
     10#include <linux/module.h>
     11
     12#define DRIVER_NAME "tifm_7xx1"
     13#define DRIVER_VERSION "0.8"
     14
     15#define TIFM_IRQ_ENABLE           0x80000000
     16#define TIFM_IRQ_SOCKMASK(x)      (x)
     17#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
     18#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
     19#define TIFM_IRQ_SETALL           0xffffffff
     20
     21static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
     22				  struct tifm_dev *sock)
     23{
     24}
     25
     26static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
     27{
     28	unsigned long flags;
     29
     30	spin_lock_irqsave(&fm->lock, flags);
     31	fm->socket_change_set |= 1 << sock->socket_id;
     32	tifm_queue_work(&fm->media_switcher);
     33	spin_unlock_irqrestore(&fm->lock, flags);
     34}
     35
     36static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
     37{
     38	struct tifm_adapter *fm = dev_id;
     39	struct tifm_dev *sock;
     40	unsigned int irq_status, cnt;
     41
     42	spin_lock(&fm->lock);
     43	irq_status = readl(fm->addr + FM_INTERRUPT_STATUS);
     44	if (irq_status == 0 || irq_status == (~0)) {
     45		spin_unlock(&fm->lock);
     46		return IRQ_NONE;
     47	}
     48
     49	if (irq_status & TIFM_IRQ_ENABLE) {
     50		writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
     51
     52		for (cnt = 0; cnt < fm->num_sockets; cnt++) {
     53			sock = fm->sockets[cnt];
     54			if (sock) {
     55				if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1))
     56					sock->data_event(sock);
     57				if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1))
     58					sock->card_event(sock);
     59			}
     60		}
     61
     62		fm->socket_change_set |= irq_status
     63					 & ((1 << fm->num_sockets) - 1);
     64	}
     65	writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
     66
     67	if (fm->finish_me)
     68		complete_all(fm->finish_me);
     69	else if (!fm->socket_change_set)
     70		writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
     71	else
     72		tifm_queue_work(&fm->media_switcher);
     73
     74	spin_unlock(&fm->lock);
     75	return IRQ_HANDLED;
     76}
     77
     78static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr)
     79{
     80	unsigned int s_state;
     81	int cnt;
     82
     83	writel(0x0e00, sock_addr + SOCK_CONTROL);
     84
     85	for (cnt = 16; cnt <= 256; cnt <<= 1) {
     86		if (!(TIFM_SOCK_STATE_POWERED
     87		      & readl(sock_addr + SOCK_PRESENT_STATE)))
     88			break;
     89
     90		msleep(cnt);
     91	}
     92
     93	s_state = readl(sock_addr + SOCK_PRESENT_STATE);
     94	if (!(TIFM_SOCK_STATE_OCCUPIED & s_state))
     95		return 0;
     96
     97	writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED,
     98	       sock_addr + SOCK_CONTROL);
     99
    100	/* xd needs some extra time before power on */
    101	if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7)
    102	    == TIFM_TYPE_XD)
    103		msleep(40);
    104
    105	writel((s_state & TIFM_CTRL_POWER_MASK) | 0x0c00,
    106	       sock_addr + SOCK_CONTROL);
    107	/* wait for power to stabilize */
    108	msleep(20);
    109	for (cnt = 16; cnt <= 256; cnt <<= 1) {
    110		if ((TIFM_SOCK_STATE_POWERED
    111		     & readl(sock_addr + SOCK_PRESENT_STATE)))
    112			break;
    113
    114		msleep(cnt);
    115	}
    116
    117	writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED),
    118	       sock_addr + SOCK_CONTROL);
    119
    120	return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7;
    121}
    122
    123inline static void tifm_7xx1_sock_power_off(char __iomem *sock_addr)
    124{
    125	writel((~TIFM_CTRL_POWER_MASK) & readl(sock_addr + SOCK_CONTROL),
    126	       sock_addr + SOCK_CONTROL);
    127}
    128
    129inline static char __iomem *
    130tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num)
    131{
    132	return base_addr + ((sock_num + 1) << 10);
    133}
    134
    135static void tifm_7xx1_switch_media(struct work_struct *work)
    136{
    137	struct tifm_adapter *fm = container_of(work, struct tifm_adapter,
    138					       media_switcher);
    139	struct tifm_dev *sock;
    140	char __iomem *sock_addr;
    141	unsigned long flags;
    142	unsigned char media_id;
    143	unsigned int socket_change_set, cnt;
    144
    145	spin_lock_irqsave(&fm->lock, flags);
    146	socket_change_set = fm->socket_change_set;
    147	fm->socket_change_set = 0;
    148
    149	dev_dbg(fm->dev.parent, "checking media set %x\n",
    150		socket_change_set);
    151
    152	if (!socket_change_set) {
    153		spin_unlock_irqrestore(&fm->lock, flags);
    154		return;
    155	}
    156
    157	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
    158		if (!(socket_change_set & (1 << cnt)))
    159			continue;
    160		sock = fm->sockets[cnt];
    161		if (sock) {
    162			printk(KERN_INFO
    163			       "%s : demand removing card from socket %u:%u\n",
    164			       dev_name(&fm->dev), fm->id, cnt);
    165			fm->sockets[cnt] = NULL;
    166			sock_addr = sock->addr;
    167			spin_unlock_irqrestore(&fm->lock, flags);
    168			device_unregister(&sock->dev);
    169			spin_lock_irqsave(&fm->lock, flags);
    170			tifm_7xx1_sock_power_off(sock_addr);
    171			writel(0x0e00, sock_addr + SOCK_CONTROL);
    172		}
    173
    174		spin_unlock_irqrestore(&fm->lock, flags);
    175
    176		media_id = tifm_7xx1_toggle_sock_power(
    177				tifm_7xx1_sock_addr(fm->addr, cnt));
    178
    179		// tifm_alloc_device will check if media_id is valid
    180		sock = tifm_alloc_device(fm, cnt, media_id);
    181		if (sock) {
    182			sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt);
    183
    184			if (!device_register(&sock->dev)) {
    185				spin_lock_irqsave(&fm->lock, flags);
    186				if (!fm->sockets[cnt]) {
    187					fm->sockets[cnt] = sock;
    188					sock = NULL;
    189				}
    190				spin_unlock_irqrestore(&fm->lock, flags);
    191			}
    192			if (sock)
    193				tifm_free_device(&sock->dev);
    194		}
    195		spin_lock_irqsave(&fm->lock, flags);
    196	}
    197
    198	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
    199	       | TIFM_IRQ_CARDMASK(socket_change_set),
    200	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
    201
    202	writel(TIFM_IRQ_FIFOMASK(socket_change_set)
    203	       | TIFM_IRQ_CARDMASK(socket_change_set),
    204	       fm->addr + FM_SET_INTERRUPT_ENABLE);
    205
    206	writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
    207	spin_unlock_irqrestore(&fm->lock, flags);
    208}
    209
    210static int __maybe_unused tifm_7xx1_suspend(struct device *dev_d)
    211{
    212	struct pci_dev *dev = to_pci_dev(dev_d);
    213	struct tifm_adapter *fm = pci_get_drvdata(dev);
    214	int cnt;
    215
    216	dev_dbg(&dev->dev, "suspending host\n");
    217
    218	for (cnt = 0; cnt < fm->num_sockets; cnt++) {
    219		if (fm->sockets[cnt])
    220			tifm_7xx1_sock_power_off(fm->sockets[cnt]->addr);
    221	}
    222
    223	device_wakeup_disable(dev_d);
    224	return 0;
    225}
    226
    227static int __maybe_unused tifm_7xx1_resume(struct device *dev_d)
    228{
    229	struct pci_dev *dev = to_pci_dev(dev_d);
    230	struct tifm_adapter *fm = pci_get_drvdata(dev);
    231	int rc;
    232	unsigned long timeout;
    233	unsigned int good_sockets = 0, bad_sockets = 0;
    234	unsigned long flags;
    235	/* Maximum number of entries is 4 */
    236	unsigned char new_ids[4];
    237	DECLARE_COMPLETION_ONSTACK(finish_resume);
    238
    239	if (WARN_ON(fm->num_sockets > ARRAY_SIZE(new_ids)))
    240		return -ENXIO;
    241
    242	pci_set_master(dev);
    243
    244	dev_dbg(&dev->dev, "resuming host\n");
    245
    246	for (rc = 0; rc < fm->num_sockets; rc++)
    247		new_ids[rc] = tifm_7xx1_toggle_sock_power(
    248					tifm_7xx1_sock_addr(fm->addr, rc));
    249	spin_lock_irqsave(&fm->lock, flags);
    250	for (rc = 0; rc < fm->num_sockets; rc++) {
    251		if (fm->sockets[rc]) {
    252			if (fm->sockets[rc]->type == new_ids[rc])
    253				good_sockets |= 1 << rc;
    254			else
    255				bad_sockets |= 1 << rc;
    256		}
    257	}
    258
    259	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
    260	       fm->addr + FM_SET_INTERRUPT_ENABLE);
    261	dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
    262		good_sockets, bad_sockets);
    263
    264	fm->socket_change_set = 0;
    265	if (good_sockets) {
    266		fm->finish_me = &finish_resume;
    267		spin_unlock_irqrestore(&fm->lock, flags);
    268		timeout = wait_for_completion_timeout(&finish_resume, HZ);
    269		dev_dbg(&dev->dev, "wait returned %lu\n", timeout);
    270		writel(TIFM_IRQ_FIFOMASK(good_sockets)
    271		       | TIFM_IRQ_CARDMASK(good_sockets),
    272		       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
    273		writel(TIFM_IRQ_FIFOMASK(good_sockets)
    274		       | TIFM_IRQ_CARDMASK(good_sockets),
    275		       fm->addr + FM_SET_INTERRUPT_ENABLE);
    276		spin_lock_irqsave(&fm->lock, flags);
    277		fm->finish_me = NULL;
    278		fm->socket_change_set ^= good_sockets & fm->socket_change_set;
    279	}
    280
    281	fm->socket_change_set |= bad_sockets;
    282	if (fm->socket_change_set)
    283		tifm_queue_work(&fm->media_switcher);
    284
    285	spin_unlock_irqrestore(&fm->lock, flags);
    286	writel(TIFM_IRQ_ENABLE,
    287	       fm->addr + FM_SET_INTERRUPT_ENABLE);
    288
    289	return 0;
    290}
    291
    292static int tifm_7xx1_dummy_has_ms_pif(struct tifm_adapter *fm,
    293				      struct tifm_dev *sock)
    294{
    295	return 0;
    296}
    297
    298static int tifm_7xx1_has_ms_pif(struct tifm_adapter *fm, struct tifm_dev *sock)
    299{
    300	if (((fm->num_sockets == 4) && (sock->socket_id == 2))
    301	    || ((fm->num_sockets == 2) && (sock->socket_id == 0)))
    302		return 1;
    303
    304	return 0;
    305}
    306
    307static int tifm_7xx1_probe(struct pci_dev *dev,
    308			   const struct pci_device_id *dev_id)
    309{
    310	struct tifm_adapter *fm;
    311	int pci_dev_busy = 0;
    312	int rc;
    313
    314	rc = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
    315	if (rc)
    316		return rc;
    317
    318	rc = pci_enable_device(dev);
    319	if (rc)
    320		return rc;
    321
    322	pci_set_master(dev);
    323
    324	rc = pci_request_regions(dev, DRIVER_NAME);
    325	if (rc) {
    326		pci_dev_busy = 1;
    327		goto err_out;
    328	}
    329
    330	pci_intx(dev, 1);
    331
    332	fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
    333				? 4 : 2, &dev->dev);
    334	if (!fm) {
    335		rc = -ENOMEM;
    336		goto err_out_int;
    337	}
    338
    339	INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
    340	fm->eject = tifm_7xx1_eject;
    341	fm->has_ms_pif = tifm_7xx1_has_ms_pif;
    342	pci_set_drvdata(dev, fm);
    343
    344	fm->addr = pci_ioremap_bar(dev, 0);
    345	if (!fm->addr) {
    346		rc = -ENODEV;
    347		goto err_out_free;
    348	}
    349
    350	rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm);
    351	if (rc)
    352		goto err_out_unmap;
    353
    354	rc = tifm_add_adapter(fm);
    355	if (rc)
    356		goto err_out_irq;
    357
    358	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
    359	       fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
    360	writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
    361	       fm->addr + FM_SET_INTERRUPT_ENABLE);
    362	return 0;
    363
    364err_out_irq:
    365	free_irq(dev->irq, fm);
    366err_out_unmap:
    367	iounmap(fm->addr);
    368err_out_free:
    369	tifm_free_adapter(fm);
    370err_out_int:
    371	pci_intx(dev, 0);
    372	pci_release_regions(dev);
    373err_out:
    374	if (!pci_dev_busy)
    375		pci_disable_device(dev);
    376	return rc;
    377}
    378
    379static void tifm_7xx1_remove(struct pci_dev *dev)
    380{
    381	struct tifm_adapter *fm = pci_get_drvdata(dev);
    382	int cnt;
    383
    384	fm->eject = tifm_7xx1_dummy_eject;
    385	fm->has_ms_pif = tifm_7xx1_dummy_has_ms_pif;
    386	writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
    387	free_irq(dev->irq, fm);
    388
    389	tifm_remove_adapter(fm);
    390
    391	for (cnt = 0; cnt < fm->num_sockets; cnt++)
    392		tifm_7xx1_sock_power_off(tifm_7xx1_sock_addr(fm->addr, cnt));
    393
    394	iounmap(fm->addr);
    395	pci_intx(dev, 0);
    396	pci_release_regions(dev);
    397
    398	pci_disable_device(dev);
    399	tifm_free_adapter(fm);
    400}
    401
    402static const struct pci_device_id tifm_7xx1_pci_tbl[] = {
    403	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID,
    404	  PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */
    405        { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID,
    406	  PCI_ANY_ID, 0, 0, 0 },
    407	{ PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID,
    408	  PCI_ANY_ID, 0, 0, 0 },
    409	{ }
    410};
    411
    412static SIMPLE_DEV_PM_OPS(tifm_7xx1_pm_ops, tifm_7xx1_suspend, tifm_7xx1_resume);
    413
    414static struct pci_driver tifm_7xx1_driver = {
    415	.name = DRIVER_NAME,
    416	.id_table = tifm_7xx1_pci_tbl,
    417	.probe = tifm_7xx1_probe,
    418	.remove = tifm_7xx1_remove,
    419	.driver.pm = &tifm_7xx1_pm_ops,
    420};
    421
    422module_pci_driver(tifm_7xx1_driver);
    423MODULE_AUTHOR("Alex Dubov");
    424MODULE_DESCRIPTION("TI FlashMedia host driver");
    425MODULE_LICENSE("GPL");
    426MODULE_DEVICE_TABLE(pci, tifm_7xx1_pci_tbl);
    427MODULE_VERSION(DRIVER_VERSION);