Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *  Q40 I/O port IDE Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *     (c) Richard Zidlicky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  License.  See the file COPYING in the main directory of this archive for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <asm/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)     /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)      *  Bases of the IDE interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)      */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define Q40IDE_NUM_HWIFS	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define PCIDE_BASE1	0x1f0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define PCIDE_BASE2	0x170
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define PCIDE_BASE3	0x1e8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define PCIDE_BASE4	0x168
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define PCIDE_BASE5	0x1e0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define PCIDE_BASE6	0x160
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) static const unsigned long pcide_bases[Q40IDE_NUM_HWIFS] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)     PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4  , PCIDE_BASE5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)     PCIDE_BASE6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static int q40ide_default_irq(unsigned long base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)            switch (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	            case 0x1f0: return 14;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		    case 0x170: return 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		    case 0x1e8: return 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		    default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	   }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Addresses are pretranslated for Q40 ISA access.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static void q40_ide_setup_ports(struct ide_hw *hw, unsigned long base, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	memset(hw, 0, sizeof(*hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	/* BIG FAT WARNING: 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	   assumption: only DATA port is ever used in 16 bit mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	hw->io_ports.data_addr = Q40_ISA_IO_W(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	hw->io_ports.error_addr = Q40_ISA_IO_B(base + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	hw->io_ports.nsect_addr = Q40_ISA_IO_B(base + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	hw->io_ports.lbal_addr = Q40_ISA_IO_B(base + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	hw->io_ports.lbam_addr = Q40_ISA_IO_B(base + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	hw->io_ports.lbah_addr = Q40_ISA_IO_B(base + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	hw->io_ports.device_addr = Q40_ISA_IO_B(base + 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	hw->io_ports.status_addr = Q40_ISA_IO_B(base + 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	hw->io_ports.ctl_addr = Q40_ISA_IO_B(base + 0x206);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	hw->irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) static void q40ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 			      void *buf, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		__ide_mm_insw(data_addr, buf, (len + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	raw_insw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static void q40ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 			       void *buf, unsigned int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	unsigned long data_addr = drive->hwif->io_ports.data_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	if (drive->media == ide_disk && cmd && (cmd->tf_flags & IDE_TFLAG_FS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		__ide_mm_outsw(data_addr, buf, (len + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	raw_outsw_swapw((u16 *)data_addr, buf, (len + 1) / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) /* Q40 has a byte-swapped IDE interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const struct ide_tp_ops q40ide_tp_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	.exec_command		= ide_exec_command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	.read_status		= ide_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	.read_altstatus		= ide_read_altstatus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	.write_devctl		= ide_write_devctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	.dev_select		= ide_dev_select,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	.tf_load		= ide_tf_load,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	.tf_read		= ide_tf_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	.input_data		= q40ide_input_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	.output_data		= q40ide_output_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const struct ide_port_info q40ide_port_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	.tp_ops			= &q40ide_tp_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	.host_flags		= IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	.irq_flags		= IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	.chipset		= ide_generic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)  * the static array is needed to have the name reported in /proc/ioports,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)  * hwif->name unfortunately isn't available yet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	"ide0", "ide1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)  *  Probe for Q40 IDE interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static int __init q40ide_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)     int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)     struct ide_hw hw[Q40IDE_NUM_HWIFS], *hws[] = { NULL, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)     if (!MACH_IS_Q40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)       return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)     printk(KERN_INFO "ide: Q40 IDE controller\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	const char *name = q40_ide_names[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (!request_region(pcide_bases[i], 8, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		printk("could not reserve ports %lx-%lx for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		       pcide_bases[i],pcide_bases[i]+8,name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	if (!request_region(pcide_bases[i]+0x206, 1, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		printk("could not reserve port %lx for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		       pcide_bases[i]+0x206,name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		release_region(pcide_bases[i], 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	q40_ide_setup_ports(&hw[i], pcide_bases[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			q40ide_default_irq(pcide_bases[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	hws[i] = &hw[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)     return ide_host_add(&q40ide_port_info, hws, Q40IDE_NUM_HWIFS, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) module_init(q40ide_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) MODULE_LICENSE("GPL");