summaryrefslogtreecommitdiffstats
path: root/programmer.c
blob: 3b4def0dc018a8b8239d091fb9136dc2153c4a66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
 * This file is part of the flashrom project.
 *
 * Copyright (C) 2009,2010,2011 Carl-Daniel Hailfinger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include "flash.h"
#include "programmer.h"

/* No-op shutdown() for programmers which don't need special handling */
int noop_shutdown(void)
{
	return 0;
}

/* Fallback map() for programmers which don't need special handling */
void *fallback_map(const char *descr, unsigned long phys_addr, size_t len)
{
	/* FIXME: Should return phys_addr. */
	return NULL;
}

/* No-op/fallback unmap() for programmers which don't need special handling */
void fallback_unmap(void *virt_addr, size_t len)
{
}

/* No-op chip_writeb() for parallel style drivers not supporting writes */
void noop_chip_writeb(const struct flashctx *flash, uint8_t val, chipaddr addr)
{
}

/* Little-endian fallback for drivers not supporting 16 bit accesses */
void fallback_chip_writew(const struct flashctx *flash, uint16_t val,
			  chipaddr addr)
{
	chip_writeb(flash, val & 0xff, addr);
	chip_writeb(flash, (val >> 8) & 0xff, addr + 1);
}

/* Little-endian fallback for drivers not supporting 16 bit accesses */
uint16_t fallback_chip_readw(const struct flashctx *flash, const chipaddr addr)
{
	uint16_t val;
	val = chip_readb(flash, addr);
	val |= chip_readb(flash, addr + 1) << 8;
	return val;
}

/* Little-endian fallback for drivers not supporting 32 bit accesses */
void fallback_chip_writel(const struct flashctx *flash, uint32_t val,
			  chipaddr addr)
{
	chip_writew(flash, val & 0xffff, addr);
	chip_writew(flash, (val >> 16) & 0xffff, addr + 2);
}

/* Little-endian fallback for drivers not supporting 32 bit accesses */
uint32_t fallback_chip_readl(const struct flashctx *flash, const chipaddr addr)
{
	uint32_t val;
	val = chip_readw(flash, addr);
	val |= chip_readw(flash, addr + 2) << 16;
	return val;
}

void fallback_chip_writen(const struct flashctx *flash, uint8_t *buf,
			  chipaddr addr, size_t len)
{
	size_t i;
	for (i = 0; i < len; i++)
		chip_writeb(flash, buf[i], addr + i);
	return;
}

void fallback_chip_readn(const struct flashctx *flash, uint8_t *buf,
			 chipaddr addr, size_t len)
{
	size_t i;
	for (i = 0; i < len; i++)
		buf[i] = chip_readb(flash, addr + i);
	return;
}

int register_par_programmer(const struct par_programmer *pgm,
			    const enum chipbustype buses)
{
	struct registered_programmer rpgm;
	if (!pgm->chip_writeb || !pgm->chip_writew || !pgm->chip_writel ||
	    !pgm->chip_writen || !pgm->chip_readb || !pgm->chip_readw ||
	    !pgm->chip_readl || !pgm->chip_readn) {
		msg_perr("%s called with incomplete programmer definition. "
			 "Please report a bug at flashrom@flashrom.org\n",
			 __func__);
		return ERROR_FLASHROM_BUG;
	}

	rpgm.buses_supported = buses;
	rpgm.par = *pgm;
	return register_programmer(&rpgm);
}

/* The limit of 4 is totally arbitrary. */
#define PROGRAMMERS_MAX 4
struct registered_programmer registered_programmers[PROGRAMMERS_MAX];
int registered_programmer_count = 0;

/* This function copies the struct registered_programmer parameter. */
int register_programmer(struct registered_programmer *pgm)
{
	if (registered_programmer_count >= PROGRAMMERS_MAX) {
		msg_perr("Tried to register more than %i programmer "
			 "interfaces.\n", PROGRAMMERS_MAX);
		return ERROR_FLASHROM_LIMIT;
	}
	registered_programmers[registered_programmer_count] = *pgm;
	registered_programmer_count++;

	return 0;
}

enum chipbustype get_buses_supported(void)
{
	int i;
	enum chipbustype ret = BUS_NONE;

	for (i = 0; i < registered_programmer_count; i++)
		ret |= registered_programmers[i].buses_supported;

	return ret;
}