brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · fb04b0b Raw
210 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* jazz_esp.c: ESP front-end for MIPS JAZZ systems.3 *4 * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)5 */6 7#include <linux/kernel.h>8#include <linux/gfp.h>9#include <linux/types.h>10#include <linux/module.h>11#include <linux/init.h>12#include <linux/interrupt.h>13#include <linux/platform_device.h>14#include <linux/dma-mapping.h>15 16#include <asm/irq.h>17#include <asm/io.h>18#include <asm/dma.h>19 20#include <asm/jazz.h>21#include <asm/jazzdma.h>22 23#include <scsi/scsi_host.h>24 25#include "esp_scsi.h"26 27#define DRV_MODULE_NAME		"jazz_esp"28#define PFX DRV_MODULE_NAME	": "29#define DRV_VERSION		"1.000"30#define DRV_MODULE_RELDATE	"May 19, 2007"31 32static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)33{34	*(volatile u8 *)(esp->regs + reg) = val;35}36 37static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)38{39	return *(volatile u8 *)(esp->regs + reg);40}41 42static int jazz_esp_irq_pending(struct esp *esp)43{44	if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)45		return 1;46	return 0;47}48 49static void jazz_esp_reset_dma(struct esp *esp)50{51	vdma_disable ((int)esp->dma_regs);52}53 54static void jazz_esp_dma_drain(struct esp *esp)55{56	/* nothing to do */57}58 59static void jazz_esp_dma_invalidate(struct esp *esp)60{61	vdma_disable ((int)esp->dma_regs);62}63 64static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,65				  u32 dma_count, int write, u8 cmd)66{67	BUG_ON(!(cmd & ESP_CMD_DMA));68 69	jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);70	jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);71	vdma_disable ((int)esp->dma_regs);72	if (write)73		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);74	else75		vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);76 77	vdma_set_addr ((int)esp->dma_regs, addr);78	vdma_set_count ((int)esp->dma_regs, dma_count);79	vdma_enable ((int)esp->dma_regs);80 81	scsi_esp_cmd(esp, cmd);82}83 84static int jazz_esp_dma_error(struct esp *esp)85{86	u32 enable = vdma_get_enable((int)esp->dma_regs);87 88	if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))89		return 1;90 91	return 0;92}93 94static const struct esp_driver_ops jazz_esp_ops = {95	.esp_write8	=	jazz_esp_write8,96	.esp_read8	=	jazz_esp_read8,97	.irq_pending	=	jazz_esp_irq_pending,98	.reset_dma	=	jazz_esp_reset_dma,99	.dma_drain	=	jazz_esp_dma_drain,100	.dma_invalidate	=	jazz_esp_dma_invalidate,101	.send_dma_cmd	=	jazz_esp_send_dma_cmd,102	.dma_error	=	jazz_esp_dma_error,103};104 105static int esp_jazz_probe(struct platform_device *dev)106{107	const struct scsi_host_template *tpnt = &scsi_esp_template;108	struct Scsi_Host *host;109	struct esp *esp;110	struct resource *res;111	int err;112 113	host = scsi_host_alloc(tpnt, sizeof(struct esp));114 115	err = -ENOMEM;116	if (!host)117		goto fail;118 119	host->max_id = 8;120	esp = shost_priv(host);121 122	esp->host = host;123	esp->dev = &dev->dev;124	esp->ops = &jazz_esp_ops;125 126	res = platform_get_resource(dev, IORESOURCE_MEM, 0);127	if (!res)128		goto fail_unlink;129 130	esp->regs = (void __iomem *)res->start;131	if (!esp->regs)132		goto fail_unlink;133 134	res = platform_get_resource(dev, IORESOURCE_MEM, 1);135	if (!res)136		goto fail_unlink;137 138	esp->dma_regs = (void __iomem *)res->start;139 140	esp->command_block = dma_alloc_coherent(esp->dev, 16,141						&esp->command_block_dma,142						GFP_KERNEL);143	if (!esp->command_block)144		goto fail_unmap_regs;145 146	host->irq = err = platform_get_irq(dev, 0);147	if (err < 0)148		goto fail_unmap_command_block;149	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);150	if (err < 0)151		goto fail_unmap_command_block;152 153	esp->scsi_id = 7;154	esp->host->this_id = esp->scsi_id;155	esp->scsi_id_mask = (1 << esp->scsi_id);156	esp->cfreq = 40000000;157 158	dev_set_drvdata(&dev->dev, esp);159 160	err = scsi_esp_register(esp);161	if (err)162		goto fail_free_irq;163 164	return 0;165 166fail_free_irq:167	free_irq(host->irq, esp);168fail_unmap_command_block:169	dma_free_coherent(esp->dev, 16,170			  esp->command_block,171			  esp->command_block_dma);172fail_unmap_regs:173fail_unlink:174	scsi_host_put(host);175fail:176	return err;177}178 179static void esp_jazz_remove(struct platform_device *dev)180{181	struct esp *esp = dev_get_drvdata(&dev->dev);182	unsigned int irq = esp->host->irq;183 184	scsi_esp_unregister(esp);185 186	free_irq(irq, esp);187	dma_free_coherent(esp->dev, 16,188			  esp->command_block,189			  esp->command_block_dma);190 191	scsi_host_put(esp->host);192}193 194/* work with hotplug and coldplug */195MODULE_ALIAS("platform:jazz_esp");196 197static struct platform_driver esp_jazz_driver = {198	.probe		= esp_jazz_probe,199	.remove_new	= esp_jazz_remove,200	.driver	= {201		.name	= "jazz_esp",202	},203};204module_platform_driver(esp_jazz_driver);205 206MODULE_DESCRIPTION("JAZZ ESP SCSI driver");207MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");208MODULE_LICENSE("GPL");209MODULE_VERSION(DRV_VERSION);210