1 /*
2 * This file is part of the flashrom project.
3 *
4 * Copyright (C) 2009 Joerg Fischer <[email protected]>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17 #include <stdlib.h>
18 #include "flash.h"
19 #include "programmer.h"
20 #include "hwaccess_physmap.h"
21 #include "platform/pci.h"
22
23 #define PCI_VENDOR_ID_DRKAISER 0x1803
24
25 #define PCI_MAGIC_DRKAISER_ADDR 0x50
26 #define PCI_MAGIC_DRKAISER_VALUE 0xa971
27
28 #define DRKAISER_MEMMAP_SIZE (1024 * 128)
29
30 /* Mask to restrict flash accesses to the 128kB memory window. */
31 #define DRKAISER_MEMMAP_MASK ((1 << 17) - 1)
32
33 struct drkaiser_data {
34 struct pci_dev *dev;
35 uint8_t *bar;
36 uint16_t flash_access;
37 };
38
39 static const struct dev_entry drkaiser_pcidev[] = {
40 {0x1803, 0x5057, OK, "Dr. Kaiser", "PC-Waechter (Actel FPGA)"},
41
42 {0},
43 };
44
drkaiser_chip_writeb(const struct flashctx * flash,uint8_t val,chipaddr addr)45 static void drkaiser_chip_writeb(const struct flashctx *flash, uint8_t val,
46 chipaddr addr)
47 {
48 struct drkaiser_data *data = flash->mst->par.data;
49
50 pci_mmio_writeb(val, data->bar + (addr & DRKAISER_MEMMAP_MASK));
51 }
52
drkaiser_chip_readb(const struct flashctx * flash,const chipaddr addr)53 static uint8_t drkaiser_chip_readb(const struct flashctx *flash,
54 const chipaddr addr)
55 {
56 struct drkaiser_data *data = flash->mst->par.data;
57
58 return pci_mmio_readb(data->bar + (addr & DRKAISER_MEMMAP_MASK));
59 }
60
drkaiser_shutdown(void * par_data)61 static int drkaiser_shutdown(void *par_data)
62 {
63 struct drkaiser_data *data = par_data;
64
65 /* Restore original flash writing state. */
66 pci_write_word(data->dev, PCI_MAGIC_DRKAISER_ADDR, data->flash_access);
67
68 free(par_data);
69 return 0;
70 }
71
72 static const struct par_master par_master_drkaiser = {
73 .chip_readb = drkaiser_chip_readb,
74 .chip_writeb = drkaiser_chip_writeb,
75 .shutdown = drkaiser_shutdown,
76 };
77
drkaiser_init(const struct programmer_cfg * cfg)78 static int drkaiser_init(const struct programmer_cfg *cfg)
79 {
80 struct pci_dev *dev = NULL;
81 uint32_t addr;
82 uint8_t *bar;
83
84 dev = pcidev_init(cfg, drkaiser_pcidev, PCI_BASE_ADDRESS_2);
85 if (!dev)
86 return 1;
87
88 addr = pcidev_readbar(dev, PCI_BASE_ADDRESS_2);
89 if (!addr)
90 return 1;
91
92 /* Map 128kB flash memory window. */
93 bar = rphysmap("Dr. Kaiser PC-Waechter flash memory", addr, DRKAISER_MEMMAP_SIZE);
94 if (bar == ERROR_PTR)
95 return 1;
96
97 struct drkaiser_data *data = calloc(1, sizeof(*data));
98 if (!data) {
99 msg_perr("Unable to allocate space for PAR master data\n");
100 return 1;
101 }
102 data->dev = dev;
103 data->bar = bar;
104
105 /* Write magic register to enable flash write. */
106 data->flash_access = pci_read_word(dev, PCI_MAGIC_DRKAISER_ADDR);
107 pci_write_word(dev, PCI_MAGIC_DRKAISER_ADDR, PCI_MAGIC_DRKAISER_VALUE);
108
109 max_rom_decode.parallel = 128 * 1024;
110
111 return register_par_master(&par_master_drkaiser, BUS_PARALLEL, data);
112 }
113
114 const struct programmer_entry programmer_drkaiser = {
115 .name = "drkaiser",
116 .type = PCI,
117 .devs.dev = drkaiser_pcidev,
118 .init = drkaiser_init,
119 };
120